linux字符设备驱动学习

 今天学习了在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");

 

 

第一次学习写驱动,跑成功了,高兴。。。

继续努力,小菜鸟~~~~~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值