|
驱动源码:
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#define DEVICE_NAME "LEDS"
int HELLO_MAJOR;
//使用mdev机制自动创建设备节点
static struct class *myfrist_hello_class;
static struct class_devicd *myfrist_hello_class_devs;
/* 用来指定LED所用的GPIO引脚 */
static unsigned long gpio_table [] =
{
S3C2410_GPB5,
S3C2410_GPB6,
S3C2410_GPB7,
S3C2410_GPB8,
};
/* 用来指定GPIO引脚的功能:输出 */
static unsigned int gpio_cfg_table [] =
{
S3C2410_GPB5_OUTP,
S3C2410_GPB6_OUTP,
S3C2410_GPB7_OUTP,
S3C2410_GPB8_OUTP,
};
static int LEDSgpio_ioctl(
struct inode *inode,
struct file *file,
unsigned int cmd,
unsigned long arg)
{
int i;
if (arg > 5)
{
return -EINVAL;
}
switch(arg)
{
case 0:
for(i=0;i<4;i++)
s3c2410_gpio_setpin(gpio_table[i],cmd);
if(cmd == 1)
printk("LED1~LED4 on\n");
else
printk("LED1~LED4 off\n");
return 0;
case 1:
{
// 设置指定引脚的输出电平为0
s3c2410_gpio_setpin(gpio_table[arg-1], cmd);
printk("cmd=%d\n",cmd);
if(cmd==1)
printk("LED1 off\n");
else
printk("LED1 on\n");
return 0;
}
case 2:
{
// 设置指定引脚的输出电平为1
s3c2410_gpio_setpin(gpio_table[arg-1], cmd);
printk("cmd=%d\n",cmd);
if(cmd==1)
printk("LED2 off\n");
else
printk("LED2 on\n");
return 0;
}
case 3:
{
// 设置指定引脚的输出电平为1
s3c2410_gpio_setpin(gpio_table[arg-1], cmd);
if(cmd==1)
printk("LED3 off\n");
else
printk("LED3 on\n");
return 0;
}
case 4:
{
// 设置指定引脚的输出电平为1
s3c2410_gpio_setpin(gpio_table[arg-1], cmd);
if(cmd==1)
printk("LED4 off\n");
else
printk("LED4 on\n");
return 0;
}
case 5:
for(i=0;i<4;i++)
s3c2410_gpio_setpin(gpio_table[i],1);
printk("LED1~LED4 off\n");
return 0;
default:
return -EINVAL;
}
}
/* 这个结构是字符设备驱动程序的核心
* 当应用程序操作设备文件时所调用的open、read、write等函数,
* 最终会调用这个结构中指定的对应函数
*/
static struct file_operations myfrist_dev_fops={
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
.ioctl = LEDSgpio_ioctl
};
static int __init LEDS_init(void)
{
int i;
HELLO_MAJOR = register_chrdev(0,DEVICE_NAME,&myfrist_dev_fops );//注册程序
//自动创建设备节点
for (i = 0; i < 4; i++)
{
s3c2410_gpio_cfgpin(gpio_table[i], gpio_cfg_table[i]);
s3c2410_gpio_setpin(gpio_table[i], 0);
}
myfrist_hello_class = class_create(THIS_MODULE,"myfrist_hello");
myfrist_hello_class_devs = device_create(myfrist_hello_class,NULL,MKDEV(HELLO_MAJOR,0),NULL,"LEDS");
if(HELLO_MAJOR < 0)
{
printk(DEVICE_NAME "canot register major number");
return HELLO_MAJOR;
}
printk("1--LED on\n");
printk("0--LED off\n");
printk(DEVICE_NAME"init yes \n");
return 0;
}
static void __exit LEDS_exit(void)
{
unregister_chrdev(HELLO_MAJOR,DEVICE_NAME); //注销程序
//注销设备节点
device_unregister(myfrist_hello_class_devs);
class_destroy(myfrist_hello_class);
printk(DEVICE_NAME"go back\n");
}
module_init(LEDS_init);
module_exit(LEDS_exit);
MODULE_LICENSE("GPL");
编译之后如下
make[1]: Leaving directory `/home/a123/lx/linux-2.6.30.4'
rm -rf modules.order
root@a123-virtual-machine:/mnt/hgfs/Ub/LEDS# make
make -C /home/a123/lx/linux-2.6.30.4 M=`pwd` modules
make[1]: Entering directory `/home/a123/lx/linux-2.6.30.4'
CC [M] /mnt/hgfs/Ub/LEDS/leds.o
/mnt/hgfs/Ub/LEDS/leds.c: In function 'LEDS_init':
/mnt/hgfs/Ub/LEDS/leds.c:144: warning: assignment from incompatible pointer type
/mnt/hgfs/Ub/LEDS/leds.c: In function 'LEDS_exit':
/mnt/hgfs/Ub/LEDS/leds.c:162: warning: passing argument 1 of 'device_unregister' from
incompatible pointer type
Building modules, stage 2.
make[2]: Warning: File `/mnt/hgfs/Ub/LEDS/leds.o' has modification time 1.1 s in the future
MODPOST 1 modules
CC /mnt/hgfs/Ub/LEDS/leds.mod.o
LD [M] /mnt/hgfs/Ub/LEDS/leds.ko
make[2]: warning: Clock skew detected. Your build may be incomplete.
make[1]: Leaving directory `/home/a123/lx/linux-2.6.30.4'
root@a123-virtual-machine:/mnt/hgfs/Ub/LEDS#
其中144行内容为
myfrist_hello_class_devs = device_create(myfrist_hello_class,NULL,MKDEV(HELLO_MAJOR,0),NULL,"LEDS");
162行内容为
device_unregister(myfrist_hello_class_devs);
虽然也能正常的运行实现想要的功能,但有警告心里总是不踏实,求助 |
|