今天学习了在linux2.6平台下的 char drvier ,在linux下推荐使用的是cdev结构体来实现对character设备的描述,代码如下
/*This module is desired for sunplusapp s3c2440_board */
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/errno.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/platform_device.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <asm/system.h>
#define DEVICE_NAME "LED_S3C2440"
struct LED_dev{
struct cdev cdev;
char name[10];
/*...*/
}*LED_devp;
static dev_t LED_device_num;
static struct class *LED_class;
//struct class *LED_class;
static unsigned long LED_table[]={
S3C2410_GPG0,
S3C2410_GPG1,
S3C2410_GPG2,
};
static unsigned int LED_cfg_table[]={
S3C2410_GPG0_OUTP,
S3C2410_GPG1_OUTP,
S3C2410_GPG2_OUTP,
};
int LED_open(struct inode *inode, struct file *filp)
{
/*将设备结构体指针赋值给文件私有数据指针*/
filp->private_data = LED_devp;
printk("Open OK/n");
return 0;
}
/*文件释放函数*/
int LED_release(struct inode *inode, struct file *filp)
{
printk("Release OK/n");
return 0;
}
static ssize_t LED_write(struct file *filp,const char __user *buf,size_t size,loff_t *f_pos)
{
unsigned char buff = 0;
int ret;
int i;
/*用户空间->内核空间*/
if (copy_from_user(&buff, buf, size))
ret = - EFAULT;
printk("write:buff=0x%x,buff=0x%x,count=%d/n", buff, buf, size);
buff-=0x30;
for(i=0;i<3;i++)
{
if(i==buff)
s3c2410_gpio_setpin(LED_table[i],1);
else
s3c2410_gpio_setpin(LED_table[i],0);
}
}
static struct file_operations led_fops = {
.owner = THIS_MODULE,
.open = LED_open,
.release = LED_release,
// .read = LED_read,
.write = LED_write,
// .llseek = LED_llseek,
// .ioctl = LED_iocrl,
};
static int __init LED_init(void)
{
int i;
int result;
if(alloc_chrdev_region(&LED_device_num,0,1,DEVICE_NAME)<0)
{
printk(KERN_DEBUG"Can't regeist LED driver/n");
return -1;
}
printk("alliok OK/n");
LED_devp = kmalloc(sizeof(struct LED_dev), GFP_KERNEL);
if (!LED_devp) /*申请失败*/
{
result = - ENOMEM;
return 1;
}
memset(LED_devp, 0, sizeof(struct LED_dev));
LED_class = class_create(THIS_MODULE, DEVICE_NAME);
cdev_init(&LED_devp->cdev,&led_fops);
LED_devp->cdev.owner = THIS_MODULE;
LED_devp->cdev.ops = &led_fops;
printk("cdev init OK/n");
if(cdev_add(&LED_devp->cdev,LED_device_num,1))
{
printk("cdev add error!/n");
return 1;
}
for(i=0;i<3;i++)
{
s3c2410_gpio_cfgpin(LED_table[i],LED_cfg_table[i]);
s3c2410_gpio_setpin(LED_table[i],0);
}
device_create(LED_class, NULL, LED_device_num,
NULL, DEVICE_NAME); //将设备在/dev下面创建节点
printk("LED driver initialized!/n");
return 0;
}
static void __exit LED_exit(void)
{
int i;
for(i=0;i<3;i++)
{
s3c2410_gpio_setpin(LED_table[i],0);
}
cdev_del(&LED_devp->cdev); /*注销cdev*/
kfree(LED_devp); /*释放设备结构体内存*/
unregister_chrdev_region(LED_device_num, 1); /*释放设备号*/
device_destroy(LED_class, LED_device_num);
class_destroy(LED_class);
return;
}
module_init(LED_init);
module_exit(LED_exit);
MODULE_LICENSE("GPL");
第一次学习写驱动,跑成功了,高兴。。。
继续努力,小菜鸟~~~~~~~