Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1254245
  • 博文数量: 404
  • 博客积分: 10011
  • 博客等级: 上将
  • 技术积分: 5382
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-03 16:29
文章存档

2010年(40)

2009年(140)

2008年(224)

我的朋友

分类: LINUX

2008-10-06 13:27:19

         刚开始学习宋的驱动详解,结合公司的板子原有的驱动程序,边学习边改造。
         由于是具体的项目,没有采用标准的开发板,所以不多说了。
/*   dm2016/saa7113.c
 *   很多字符设备只是简单的open,close,read,write,需要添加函数使之更加安全
 *   add: private_date  llseek()   memory:kmalloc()   fmalloc()   verify_area() contain_of()
 */
/*
#ifdef MODULE
#include
#endif
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "hi_i2c.h"

#define EEPROM_ADDR_W 0xa4
#define EEPROM_ADDR_R 0xa5
unsigned char val[2];
unsigned char r_value[6];

#define EEPROM_SIZE  0x1000  /*全局内存最大4K字节*/
#define MEM_CLEAR 0x1        /*清0全局内存*/
#define EEPROM_MAJOR 254     /*预设的eeprom的主设备号*/
static eeprom_major = GLOBALMEM_MAJOR;
/*eeprom设备结构体*/
struct eeprom_dev
{                                                       
   struct cdev cdev; /*cdev结构体*/                      
   unsigned char mem[EEPROM_SIZE]; /*全局内存*/
};
struct eeprom_dev *eeprom_devp; /*设备结构体指针*/
/*文件打开函数*/
int eeprom_open(struct inode *inode, struct file *filp)
{
   struct eeprom_dev *dev
   /*获得设备结构体指针*/
   dev = container_of(inode->i_dev,struct eeprom_dev,cdev);
   /*将设备结构体指针赋值给文件私有数据指针*/
   filp->private_data = eeprom_devp;
  if(!try_module_get(THIS_MODULE)) return -ENODEV;
 
   return 0;
}
/*文件释放函数*/
int eeprom_release(struct inode *inode, struct file *filp)
{
   module_put(THIS_MODULE);
 
   return 0;
}
/* ioctl设备控制函数 */
static int eeprom_ioctl(struct inode *inodep, struct file *filp, unsigned int cmd, unsigned long arg)
{
   struct eeprom_dev *dev = filp->private_data;/*获得设备结构体指针*/
   switch (cmd)
   {
     case MEM_CLEAR:
       memset(dev->mem, 0, EEPROM_SIZE);
       printk(KERN_INFO "eeprom is set to zero\n");
       break;
     default:
       return  - EINVAL;
   }
 
   return 0;
}

/*读函数*/
/*ssize_t -- unsigned int*/
static ssize_t eeprom_read(struct file *filp, char __user *buf, size_t size, loff_t *offset)
{
    r_value[0] = hi_i2c_read( EEPROM_ADDR_R, 0x00 );
    r_value[1] = hi_i2c_read( EEPROM_ADDR_R, 0x01 );
    r_value[2] = hi_i2c_read( EEPROM_ADDR_R, 0x02 );
    r_value[3] = hi_i2c_read( EEPROM_ADDR_R, 0x03 );
    r_value[4] = hi_i2c_read( EEPROM_ADDR_R, 0x04 );
    r_value[5] = hi_i2c_read( EEPROM_ADDR_R, 0x05 );
   
   
   unsigned long p =  *offset;
   unsigned int count = size;
 
   int ret = 0;
   struct eeprom_dev *dev = filp->private_data; /*获得设备结构体指针*/
   /*分析和获取有效的写长度*/
   if (p >= EEPROM_SIZE)
     return count ?  - ENXIO: 0;
   if (count > EEPROM_SIZE - p)
     count = EEPROM_SIZE - p;
  /*判断用户空间的有效性*/
  int err;
  err = verify_area(VERIFY_WRITE,void(*) arg,size)
   if(err < 0)  return err;
 
   /*内核空间->用户空间*/
   if ( copy_to_user( buf, r_value, sizeof(r_value)))
    {
        printk(" copy to user error\n"); 
        ret =  - EFAULT;
        return ret;
    }
   
   else
   {
     *offset += count;
     ret = count;
   
     printk(KERN_INFO "read %d bytes(s) from %d\n", count, p);
   }
 
 
   return ret;
}
/*写函数*/
static ssize_t eeprom_write(struct file *filp, const char __user *buf, size_t size, loff_t *offset)
{
   unsigned long p =  *offset;
   unsigned int count = size;
   int ret = 0;
   struct eeprom_dev *dev = filp->private_data; /*获得设备结构体指针*/
 
   /*分析和获取有效的写长度*/
   if (p >= EEPROM_SIZE)
     return count ?  - ENXIO: 0;
   if (count > EEPROM_SIZE - p)
     count = EEPROM_SIZE - p;
   
   /*判断用户空间的有效性*/
  int err;
  err = verify_area(VERIFY_READ,void(*) arg,size)
   if(err < 0)  return err;
 
   /*用户空间->内核空间*/
   /*copy_from_user---- return 0: sucess ; return no zero: error*/
   if (copy_from_user(val, buf, sizeof(buf)))
    {
       printk("\t Eeprom wrong cpy val is %0x, %0x\n",val[0],val[1]);
       ret =  - EFAULT;
    }
   else
   {
     *offset += count;
     ret = count;
   
     printk(KERN_INFO "written %d bytes(s) from %d\n", count, p);
   }
   printk("val[0]=%0x   val[1]=%0x\n",val[0],val[1]);
    if( hi_i2c_write( EEPROM_ADDR_W, val[0] ,val[1] ))
    {
        printk("i2c write error\n");
    }
  
   return ret;
}
/* seek文件定位函数 */
static loff_t eeprom_llseek(struct file *filp, loff_t offset, int orig)
{
   loff_t ret = 0;
   switch (orig)
   {
     case 0:   /*相对文件开始位置偏移*/
       if (offset < 0)
       {
         ret =  - EINVAL;
         break;
       }
       if ((unsigned int)offset > EEPROM_SIZE)
       {
         ret =  - EINVAL;
         break;
       }
       filp->f_pos = (unsigned int)offset;
       ret = filp->f_pos;
       break;
     case 1:   /*相对文件当前位置偏移*/
       if ((filp->f_pos + offset) > EEPROM_SIZE)
       {
         ret =  - EINVAL;
         break;
       }
       if ((filp->f_pos + offset) < 0)
       {
         ret =  - EINVAL;
         break;
       }
       filp->f_pos += offset;
       ret = filp->f_pos;
       break;
     default:
       ret =  - EINVAL;
       break;
   }
 
   return ret;
}
/*文件操作结构体*/
static const struct file_operations eeprom_fops =
{
   .owner        = THIS_MODULE,
   .llseek   = eeprom_llseek,
   .read         = eeprom_read,
   .write        = eeprom_write,
   .ioctl        = eeprom_ioctl,
   .open         = eeprom_open,
   .release  = eeprom_release,
};

static int eeprom_device_init(void)
{
    printk("into eeprom device init\n");
   
    return 0;
}
/*初始化并注册cdev*/
static void eeprom_setup_cdev(struct eeprom_dev *dev, int index)
{
   int err, devno = MKDEV(eeprom_major, index);
 
   cdev_init(&dev->cdev, &eeprom_fops);
   dev->cdev.owner = THIS_MODULE;
   dev->cdev.ops = &eeprom_fops;
   err = cdev_add(&dev->cdev, devno, 1);
   if (err)
     printk(KERN_NOTICE "Error %d adding EEPROM%d", err, index);
}
/*设备驱动模块加载函数*/
static int __init eeprom_init(void)
{
   int result = 0;
   dev_t devno = MKDEV(eeprom_major, 0);
     /* 申请设备号*/
   if (eeprom_major)
     result = register_chrdev_region(devno,1,"eeprom"); 
   else  /* 动态申请设备号 */
   {
     result = alloc_chrdev_region(&devno, 0, 1, "eeprom");
     eeprom_major = MAJOR(devno);
   }
   if(result)
     {
         printk("could not register eeprom devices. \n");
         return result;
     }
   if (result < 0)
     return result;
  
   /* 动态申请设备结构体的内存*/
   eeprom_devp = kmalloc(sizeof(struct eeprom_dev), GFP_KERNEL);
   if (!eeprom_devp)    /*申请失败*/
   {
     result =  - ENOMEM;
     goto fail_malloc;
   }
   memset(eeprom_devp, 0, sizeof(struct eeprom_dev));
  
   eeprom_setup_cdev(eeprom_devp, 0);
   return 0;
 
   fail_malloc: unregister_chrdev_region(devno, 1);
   return result;
  
        
   if(eeprom_device_init()!=0)
   {
       unregister_chrdev_region(MKDEV(eeprom,0),1)
       printk("eeprom driver init fail for device init error!\n");
        
       return -1;
   }
    
   printk("eeprom driver init successful!\n");
  
   return ret;
}

/*模块卸载函数*/
static void __exit eeprom_exit(void)
{
    cdev_del(&eeprom_devp->cdev);   /*注销cdev*/
   kfree(eeprom_devp);     /*释放设备结构体内存*/
    unregister_chrdev_region(MKDEV(eeprom,0),1);/*释放设备号*/
}
MODULE_INFO(build, UTS_VERSION);
MODULE_AUTHOR("yu chuan");
MODULE_LICENSE("Dual BSD/GPL");
module_param(eeprom_major, int, S_IRUGO);
module_init(eeprom_init);
module_exit(eeprom_exit);
 
    这个和宋的模板很像吧,的确,其实本来驱动就是这样的,用宋的话:点面结合,框架学习更重要!
 
                               下一步增加并发处理
阅读(1718) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

czr20072009-06-28 09:47:29

产品简介 有一款防抄板保密芯片,通过一个解密算法和与之相对应的128bit密钥,有效地保护了软件设计。当输入的暗文执行解密算法之后,产生的数据等于加密端输入的明文时,解密通过主机程序往下执行,否则程序退出执行。密钥存储在128bit OTP中,该芯片除了解密功能之外,内嵌1024bit E2PROM,可以作为数据保存,采用I2C总线进行数据传输。 产品特点: 支持高达128bit密钥解密算法 支持I2C总线通讯接口 支持I2C一位设备地址 密钥存储在128bit OTP中,烧录时直接写入,一次写入,不能读出 内嵌1024bit E2PROM SOP8封装 欢迎来电咨询索取相关资料 EAIL:hjwf2000@163.com 联系电话:0755-89812241 陈先生