Chinaunix首页 | 论坛 | 博客
  • 博客访问: 21056
  • 博文数量: 10
  • 博客积分: 400
  • 博客等级: 下士
  • 技术积分: 110
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-15 10:14
文章分类

全部博文(10)

文章存档

2010年(2)

2009年(8)

我的朋友

分类: LINUX

2010-07-21 10:31:55

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define      LEDS_NAME    "led"
#define      LEDS_COUNT    1
#define      LEDS_MAJOR    0
#define      LEDS_MINOR    0
MODULE_LICENSE("Dual BSD/GPL");
dev_t devid;
static struct cdev  *led_dev;
static struct class *led_class;
static unsigned long led_pin[] = {
 S3C2410_GPB(5),
 S3C2410_GPB(6),
 S3C2410_GPB(7),
 S3C2410_GPB(8),
};
static unsigned int led_cfg[] = {
 S3C2410_GPIO_OUTPUT,
 S3C2410_GPIO_OUTPUT,
 S3C2410_GPIO_OUTPUT,
 S3C2410_GPIO_OUTPUT,
};
static char led_flag[4]={
 '1',
 '1',
 '1',
 '1',
};
static int led_open(struct inode *inode, struct file *filp)
{
int i;
 for(i = 0; i < 4 ;i ++)
        {
                s3c2410_gpio_cfgpin(led_pin[i],led_cfg[i]);
                s3c2410_gpio_setpin(led_pin[i],(int)(led_flag[i] - '0'));
        }
 printk("open led ok\n");
     return 0;
}
static ssize_t led_read(struct file *filp, char __user *buff, size_t size, loff_t *ppos)
{
 if (size > 4)
 {
  return -EFAULT;
 }
 if(copy_to_user(buff,(void *)led_flag,size))
 {
  return -EFAULT; 
 }
 return size;
}
static ssize_t led_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
int i;
 if (size > 4)
 {
  return -EFAULT;
 }
 if(copy_from_user(led_flag,buf,size))
 {
  return -EFAULT;
 }
 for(i = 0; i < size;i ++)
 {
  s3c2410_gpio_setpin(led_pin[i],(int)(led_flag[i] - '0'));
 } 
 return size;
}
static int led_ioctl(struct inode *inodep,struct file *filp, unsigned int cmd,unsigned long arg)
{
 if((cmd > 1)||(arg > 3))
 {
  return -EFAULT;
 }
 switch(cmd)
 {
 case 0:
 case 1:
        s3c2410_gpio_setpin(led_pin[arg],cmd);
        led_flag[arg] = cmd + '0'; 
        return 0;
        break;
 default:
        return -EINVAL;
        break;
 }
}
static int led_release(struct inode *inode, struct file *filp)
{
int i;
 for(i =0 ;i < 4;i++)
 {
 s3c2410_gpio_setpin(led_pin[i],1);
 }
 return 0;
}
static struct file_operations led_fops = {
 .owner = THIS_MODULE,
 .open  = led_open,
 .read  = led_read,
 .write = led_write,
 .ioctl = led_ioctl,
 .release = led_release,
};

static void led_setup(void)
{
int ret;
 cdev_init(led_dev,&led_fops); //初始化 cdev
 led_dev->owner = THIS_MODULE;
 led_dev->ops   = &led_fops;  
 ret = cdev_add(led_dev,devid,LEDS_COUNT);//添加注册设备
 if(IS_ERR(&ret))
 {
  printk("Error:%d adding leds!\n",ret);
 }
}
static int __init led_init(void)
{
int ret;
 if(LEDS_MAJOR)//判断是动态申请设备号还是静态申请
 {
  devid = MKDEV(LEDS_MAJOR,LEDS_MINOR);//根据主、次设备号 得到设备号
  ret = register_chrdev_region(devid,LEDS_COUNT,LEDS_NAME);//静态申请函数
  
 }
 else
 {
  ret = alloc_chrdev_region(&devid,LEDS_MINOR,1,LEDS_NAME);//动态申请函数
 }
 if(ret < 0)
 {
  printk("Can't register major number!\n");
  return ret;
 }
 
 led_dev = kmalloc(sizeof(struct cdev),GFP_KERNEL);//为cdev结构动态申请内核空间
 if(!led_dev)
 {
  ret = -ENOMEM;//失败返回值
  goto fail_malloc;
 }
 memset(led_dev,0,sizeof(struct cdev));//格式化led_dev设备结构
 led_setup(); 
 
 led_class = class_create(THIS_MODULE,LEDS_NAME);//注册一个类,使mdev在"dev/"下面为设备建立设备节点
 if(IS_ERR(led_class))
 {
  printk("Error:Failed to create led_class!\n");
  return -1;//建立设备节点失败
 }
 device_create(led_class,NULL,devid,NULL,LEDS_NAME);//创建设备节点 名字为LEDS_NAME
 printk("%s Init ok!\n",LEDS_NAME);
 return 0;
fail_malloc:
 unregister_chrdev_region(devid,LEDS_COUNT);//注销从devid这个设备号开始的LEDS_COUNT个设备号
 return ret;
}
static void __exit led_exit(void)
{
 
 
 cdev_del(led_dev);
 kfree(led_dev);
 unregister_chrdev_region(devid,LEDS_COUNT);
 
 device_destroy(led_class, devid);
     class_destroy(led_class);
}
module_init(led_init);
module_exit(led_exit);
阅读(237) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~