Android驱动例子(LED灯控制)
[日期:2011-04-13] | 来源:Linux社区 |
要达到的效果:通过Android的应用,调用驱动程序,在开发板上控制4个LED的亮灭。
一、硬件原理
如上图,通过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
- #include <linux/kernel.h>
- #include <linux/sched.h>
- #include <linux/timer.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <mach/hardware.h>
- #include <asm/io.h>
- #include <asm/uaccess.h>
- #include <plat/gpio-cfg.h>
- #include <plat/regs-clock.h>
- #include <plat/regs-lcd.h>
- #include <plat/regs-gpio.h>
- #include <mach/map.h>
- #include <linux/gpio.h>
- #include <plat/gpio-bank-m.h>
- #include <linux/cdev.h>
- #include <linux/fs.h> //for register_chrdev()
- #include <linux/device.h>
- #include <mach/map.h>
- #include "leddriver.h"
- #include <linux/miscdevice.h>
- #include <linux/watchdog.h>
- #include <linux/fs.h>
- #define Viberator_MAJOR
97 //?÷éè±?o? - #define SCULL_NR_DEVS
4 - #define SCULL_QUANTUM
4000 - #define SCULL_QSET
1000 - //---do as the GIO driver
- #define DEVCOUNT
4 - #define GIO_MINOR
2 - static dev_t dev;
//éê ?? μ?μ??÷ éè±? o? - static struct cdev *cdev_p;
- static int openCnt;
- //--è???±?á?------------
- int VIB_major
= 97;//we asigment it for test - int VIB_minor = 0;
- int VIB_nr_devs = SCULL_NR_DEVS;
- int VIB_quantum = SCULL_QUANTUM;
- int VIB_qset = SCULL_QSET;
-
- static struct class *vib_dev_class;
- #define GPNCON
S3C64XX_GPNCON - #define GPNDAT
S3C64XX_GPNDAT - #define GPNPUD
S3C64XX_GPNPUD - #define GPMCON S3C64XX_GPMCON
- #define GPMDAT
S3C64XX_GPMDAT - #define GPMPUD S3C64XX_GPMPUD
-
- #define VIB_ON 0x11
-
#defineVIB_OFF 0x22 - static const struct file_operations GPIO_Viberator_ctl_ops={
-
.owner = THIS_MODULE, -
.open = GPIO_VIB_open, -
.read =GPIO_VIB_read, -
.write =GPIO_VIB_write, -
.ioctl = GPIO_VIB_ioctl, -
.release =GPIO_VIB_release, - };
- ssize_t GPIO_VIB_read(struct file * file,char * buf,size_t count,loff_t * f_ops)
- {
-
printk(" GPIO_VIB_read \r\n"); -
gpio_direction_output(S3C64XX_GPM(3), 0);// -
return count ; - }
- ssize_t GPIO_VIB_write (struct file * file,const char * buf, size_t count,loff_t * f_ops)
- {
-
printk(" GPIO_VIB_write \r\n"); -
gpio_direction_output(S3C64XX_GPM(3), 1);// -
return count; - }
-
- //ssize_t GPIO_VIB_ioctl(struct inode *
inode,struct file * file,unsigned int cmd, long data) - static int GPIO_VIB_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
- {
-
printk(KERN_ERR"VIB:GPIO_VIB_ioctl --CMD=%x \n",cmd); -
switch(cmd) -
{ -
case VIB_ON: -
gpio_direction_output(S3C64XX_GPM(1), 0);// -
gpio_direction_output(S3C64XX_GPM(2), 0);// -
gpio_direction_output(S3C64XX_GPM(3), 0);// -
gpio_direction_output(S3C64XX_GPM(4), 1);// -
printk(KERN_ERR"VIB:GPIO_VIB_ioctl --VIB_ON\n"); -
break; -
case VIB_OFF: -
{ -
printk(KERN_ERR"VIB:GPIO_VIB_ioctl --VIB_OFF\n"); -
gpio_direction_output(S3C64XX_GPM(1), 1);// -
gpio_direction_output(S3C64XX_GPM(2), 1);// -
gpio_direction_output(S3C64XX_GPM(3), 1);// -
gpio_direction_output(S3C64XX_GPM(4), 0);// -
break; -
} -
default:break; -
-
} -
//gpio_free(S3C64XX_GPN(7)); - }
- ssize_t GPIO_VIB_open(struct inode * inode,struct file * file)
- {
- //?£?éêy
-
//MOD_INC_USE_COUNT; -
printk("GPIO_VIB_open() \n"); -
return 0; - }
- ssize_t GPIO_VIB_release(struct inode * inode, struct file * file)
- {
-
// MOD_DEC_USE_COUNT;//?£?éêy?? -
printk("GPIO_VIB_release() \n"); -
return 0; - }
- static int GPIO_VIB_CTL_init(void)
- {
-
int ret = -ENODEV; -
int error ; -
printk("---------------------------------------------- \r\n"); -
//3?ê??ˉ???ú -
s3c_gpio_cfgpin(S3C64XX_GPM(1), S3C_GPIO_SFN(1));//GPM1 output -
s3c_gpio_cfgpin(S3C64XX_GPM(2), S3C_GPIO_SFN(1));//GPM2 output -
s3c_gpio_cfgpin(S3C64XX_GPM(3), S3C_GPIO_SFN(1));//GPM3 output -
s3c_gpio_cfgpin(S3C64XX_GPM(4), S3C_GPIO_SFN(1));//GPM4 output - #if 1
- ret = register_chrdev(Viberator_MAJOR, "viberator", &GPIO_Viberator_ctl_ops);
- if (ret < 0) {
-
printk(KERN_ERR "VIB: unable to get major %d\n", ret); -
return ret; - }
- //′′?¨\uc1class
- vib_dev_class = class_create(THIS_MODULE, "viberator");
- if (IS_ERR(vib_dev_class)) {
-
unregister_chrdev(Viberator_MAJOR, "capi20"); -
return PTR_ERR(vib_dev_class); - }
- //′′?¨?úμ?£?
- device_create(vib_dev_class, NULL, MKDEV(Viberator_MAJOR, 0), NULL, "vib");
- // create a point under /dev/class/vib
- //í¨1yé????aá?2?£??y?ˉ?ó??oó£??í?á?ú/dev/class/????éú3é\uc1vib?úμ?£?ó|ó?3ìDò?éò???2ù×÷???t???ù2ù×÷?a???úμ?£?í¨1y\uc1open ,write,read μèoˉêy2ù×÷£??ê?é?éò??′oó??μ?ó|ó?ê?ày3ìDò?£
-
return 0; - #endif
- #if 0
-
if ((error = alloc_chrdev_region(&dev, 0, DEVCOUNT, "vibrate")) < 0) -
{ -
printk(KERN_ERR -
"VIB: Couldn't alloc_chrdev_region, error=%d\n", -
error); -
return 1; -
} -
printk("dev = %d \n",dev); -
cdev_p = cdev_alloc(); -
cdev_p->ops = &GPIO_Viberator_ctl_ops; -
error = cdev_add(cdev_p, dev, DEVCOUNT); -
if (error) { -
printk(KERN_ERR -
"VIB: Couldn't cdev_add, error=%d\n", error); -
return 1; -
} -
-
vib_dev_class = class_create(THIS_MODULE, "vib-dev"); -
if (IS_ERR(vib_dev_class)) { -
res = PTR_ERR(vib_dev_class); -
goto out_unreg_class; -
} -
return 0; - #endif
- out_unreg_class:
-
class_destroy(vib_dev_class); - return 1;
- }
-
- static int __init S3C6410_VIB_init(void)
- {
-
int ret = -ENODEV; -
//μ÷ó?oˉêy -
printk(KERN_ERR "Auly: S3C6410_VIB_init---\n"); -
ret = GPIO_VIB_CTL_init(); -
if(ret) -
{ -
printk(KERN_ERR "Auly: S3C6410_VIB_init--Fail !!!\n"); -
return ret; -
} -
return 0; - }
- static void __exit cleanup_GPIO_VIB(void)
- {
-
//×¢?úéè±? -
// devfs_unregister_chrdev(Viberator_MAJOR,"gpio_vib_ctl"); - #if 0
-
cdev_del(cdev_p); -
unregister_chrdev_region(dev, DEVCOUNT); -
class_destroy(vib_dev_class); - #endif
- device_destroy(vib_dev_class, MKDEV(Viberator_MAJOR, 0));
- class_destroy(vib_dev_class);
- unregister_chrdev(Viberator_MAJOR, "viberator");
- }
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("Peter first driver");
- MODULE_ALIAS_CHARDEV(Viberator_MAJOR, 0);
-
- module_init(S3C6410_VIB_init);
- module_exit(cleanup_GPIO_VIB);