Chinaunix首页 | 论坛 | 博客
  • 博客访问: 107800
  • 博文数量: 41
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 335
  • 用 户 组: 普通用户
  • 注册时间: 2013-02-21 12:49
文章分类
文章存档

2013年(41)

我的朋友

分类: 嵌入式

2013-11-11 18:33:41

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DEVICE_NAME "vk3344"
static dev_t vk3344_number;
static struct class *vk3344_class;
int vk3344_attach( struct i2c_adapter *adapter, int address, int kind );
static int vk3344_probe( struct i2c_adapter *adapter );
static int vk3344_detach(struct i2c_adapter *adap);
int vk3344_open( struct inode *inode, struct file *file );
ssize_t vk3344_read( struct file *file, char *buf, size_t count, loff_t *ppos );
static long vk3344_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
static int vk3344_release(struct inode *inode, struct file *file);
ssize_t vk3344_write( struct file *file, char *buf, size_t count, loff_t *ppos );
static const struct file_operations vk3344_fops = {
 .owner = THIS_MODULE,
 .open = vk3344_open,
 .read = vk3344_read,
 .write = vk3344_write,
 .ioctl = vk3344_ioctl,
 .release = vk3344_release,
};

 const struct i2c_device_id vk3344_id[] = {
 { "vk3344", 0 },
 { }
};

struct vk3344_bank{
 struct i2c_client client;
 unsigned int addr;
 unsigned short current_pointer;
 int bank_number;
 struct cdev dev;
 char name[30];
}*p_bank;
static unsigned short normal_i2c[] = {
 0x48, I2C_CLIENT_END
};
static unsigned short ignore[2] = {
 I2C_CLIENT_END, I2C_CLIENT_END
};
static unsigned short probe[2] = {
 I2C_CLIENT_END, I2C_CLIENT_END
};
static struct i2c_client_address_data addr_data = {
 .normal_i2c = normal_i2c,
 .probe = probe,
 .ignore = ignore,
 .forces = NULL,
};
static struct i2c_driver vk3344_driver = {
 .driver = {
  .name = "vk3344",
  .owner = THIS_MODULE,
 },
 .id_table = vk3344_id,
 .attach_adapter = vk3344_probe,
 .detach_client = vk3344_detach,
};
int vk3344_attach( struct i2c_adapter *adapter, int address, int kind )
{
 printk( KERN_INFO "----vk3344_attach()--start--\r\n" );
 
 
 p_bank->client.driver = &vk3344_driver;
 p_bank->client.addr = address;
 p_bank->client.adapter = adapter;
 p_bank->client.flags = 0;
 strlcpy( p_bank->client.name, "vk3344", I2C_NAME_SIZE );
 
 printk( KERN_INFO "----address=%d--name=%s--\r\n", p_bank->client.addr, p_bank->client.name );
 
 if( 0 != i2c_attach_client( &p_bank->client ) )
 {
  printk( KERN_INFO "----i2c_attach_client()--error--\r\n" );
 }
 
 printk( KERN_INFO "----vk3344_attach()--end--\r\n" );
 return 0;
}
static int vk3344_probe( struct i2c_adapter *adapter )
{
 printk( KERN_INFO "----vk3344_probe()--start--\r\n" );
 
 int ret = i2c_probe( adapter, &addr_data, vk3344_attach );
 printk( KERN_INFO "----vk3344_probe()--end--ret=%d--\r\n", ret );
 
 return ret;
 
 
}
static int vk3344_detach(struct i2c_adapter *adap)
{
 return 0;
}

int vk3344_open( struct inode *inode, struct file *file )

 printk( KERN_INFO "----vk3344_open()--start--\r\n" );
// unsigned int minor = iminor(inode);
 printk( KERN_INFO "----iminor()--end--\r\n" );
 file->private_data = (struct vk3344_bank*)p_bank;
 printk( KERN_INFO "----vk3344_open()--end--\r\n" );
 
 return 0;
}
 

ssize_t vk3344_read( struct file *file, char *buf, size_t count, loff_t *ppos )
{
#if 0
 int ret;
 struct i2c_adapter *adap=p_bank->client.adapter;
 struct i2c_msg msg[2];
 int nmsg = 2;
printk( KERN_INFO "----vk3344_read()--start--\r\n" );
 if (count > 8192)
  count = 8192;
 
 char *tmp = kmalloc(count,GFP_KERNEL);
 char *reg_addr = kmalloc(count,GFP_KERNEL);
 
 if (NULL == tmp && NULL != reg_addr ){
  kfree( reg_addr );
  printk( KERN_INFO "----kmalloc()--error--\r\n" );
  return -ENOMEM;
 }
  
 if (NULL == reg_addr && NULL != tmp ){
  kfree( tmp );
  printk( KERN_INFO "----kmalloc()--error--\r\n" );
  return -ENOMEM;
 }
   
 memset( tmp, 0x00, count );
 memset( reg_addr, 0x00, count );
 reg_addr[0] = buf[0];
 tmp[0] = buf[0];
    
 msg[0].addr = p_bank->client.addr;
 msg[0].flags = p_bank->client.flags & I2C_M_TEN;
 msg[0].len = 1;
 msg[0].buf = (char *)reg_addr;
 printk( KERN_INFO "----kmalloc()msg[0].addr=%d--\r\n", msg[0].addr );
 printk( KERN_INFO "----kmalloc()msg[0].flags=%d--\r\n", msg[0].flags );
 printk( KERN_INFO "----kmalloc()msg[0].len=%d--\r\n", msg[0].len );
 printk( KERN_INFO "----kmalloc()msg[0].buf=%s--\r\n", *msg[0].buf );
 
 msg[1].addr = p_bank->client.addr;
 msg[1].flags = p_bank->client.flags & I2C_M_TEN;
 msg[1].flags |= I2C_M_RD;
 msg[1].len = count;
 msg[1].buf = (char *)tmp;
 
 printk( KERN_INFO "----kmalloc()msg[1].addr=%d--\r\n", msg[1].addr );
 printk( KERN_INFO "----kmalloc()msg[1].flags=%d--\r\n", msg[1].flags );
 printk( KERN_INFO "----kmalloc()msg[1].len=%d--\r\n", msg[1].len );
 printk( KERN_INFO "----kmalloc()msg[1].buf=%s--\r\n", *msg[1].buf );
  
 ret = i2c_transfer(adap, msg, nmsg );
 
 printk( KERN_INFO "----i2c_transfer--over--\r\n" );
 
 if (ret >= 0)
 {
  printk( KERN_INFO "----i2c_transfer--ok--\r\n" );
  ret = copy_to_user(buf,tmp,count)?-EFAULT:ret;
   printk( KERN_INFO "----copy_to_user--ok--\r\n" );
 }
 else
 {
  printk( KERN_INFO "----i2c_transfer--000--\r\n" );
 }
  
 kfree(tmp);
 kfree( reg_addr );
 
 printk( KERN_INFO "----kfree--ok--\r\n" );
 
#else
printk( KERN_INFO "----vk3344_read()--start--\r\n" );
// if (count > 8192)
//  count = 8192;
 
 unsigned char reg_addr[2] = {0}; 
 unsigned char tmp[2] = {0};//kmalloc(count,GFP_KERNEL);
 int len = 1;//count > 1 ? count-1 : 0;
 int ret = 0;
   
 // send the reg addr
 reg_addr[0] = buf[0];
 printk( KERN_INFO "----reg_addr[0]=%d----\r\n", reg_addr[0] );
 ret = i2c_master_send( &p_bank->client, reg_addr, 1 );
 if (ret != 1)
 {
  printk( KERN_INFO "----i2c_read()--i2c_master_send--error--ret=%d\r\n", ret );
 // kfree( tmp );
  return -EIO;
 }
 else
 {
  printk( KERN_INFO "----i2c_read()--i2c_master_send--ok--ret=%d\r\n", ret );
 }
 msleep( 20 );
 // read data
 ret = i2c_master_recv(&p_bank->client,tmp,len);
 if (ret >= 0)
 {
  printk( KERN_INFO "----i2c_read()--rcv--ok--tmp[0]=%d,tmp[1]=%d--len=%d--ret=%d\r\n", ret, tmp[0],
tmp[1], len );
  ret = copy_to_user(buf,tmp,len)?-EFAULT:ret;
  printk( KERN_INFO "--copy_to_user()--ret=%d\r\n", ret );
  return len;
 }
 else
 {
  printk( KERN_INFO "----i2c_read()--i2c_master_recv--error--ret=%d\r\n", ret );
 } 
 
// kfree(tmp);
#endif 
 return 0;
}
ssize_t vk3344_write( struct file *file, char *buf, size_t count, loff_t *ppos )
{
#if 0
 int ret;
 struct i2c_msg msg;
 struct i2c_adapter *adap=p_bank->client.adapter;
 char *tmp = kmalloc(count,GFP_KERNEL);
 
 if (count > 8192)
  count = 8192;

 if (tmp==NULL)
  return -ENOMEM;
  
 if (copy_from_user(tmp,buf,count)) {
  kfree(tmp);
  return -EFAULT;
 }
 
 msg.addr = p_bank->client.addr;
 msg.flags = p_bank->client.flags & I2C_M_TEN;
 msg.len = count;
 msg.buf = (char *)tmp; 
 ret = i2c_transfer(adap, &msg, 1);
  
 kfree(tmp);
#else
 int ret = 0;
 unsigned char reg_data[2]={buf[0],buf[1]};
 msleep( 20 );
 ret = i2c_master_send( &p_bank->client, reg_data, 2 );
 if (ret != sizeof(reg_data))
 {
  printk( KERN_INFO "----vk3344_write()--i2c_master_send--error--ret=%d\r\n", ret );
  return -EIO;
 }
 else
 {
  printk( KERN_INFO "----vk3344_write()--i2c_master_send--ok--reg_data[0]=%d,reg_data[1]=%d\r\n",
reg_data[0], reg_data[1] );
 }
  
#endif 
 return (ret == 1) ? count : ret;
}
static long vk3344_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
 return 0;
}
static int vk3344_release(struct inode *inode, struct file *file)
{
// struct i2c_client *client = file->private_data->client;
// i2c_put_adapter(client.adapter);
// kfree(client);
 file->private_data = NULL;
 return 0;
}

int __init vk3344_init(void)
{
 printk( KERN_INFO "--vk3344_init()-- start--\r\n" );
 p_bank = kmalloc( sizeof( struct vk3344_bank ), GFP_KERNEL );
 if( !p_bank )
 {
  printk( KERN_INFO "--kmalloc()-- ERROR--\r\n" );
  return -1;
 }
 memset( p_bank, 0x00, sizeof( struct vk3344_bank ) );
 
 vk3344_number = 0;
 //register_chrdev_region( vk3344_number, 1, "vk3344");
 printk( KERN_INFO "--class_create()-- start--\r\n" );
 if ( alloc_chrdev_region( &vk3344_number, 0, 1, "vk3344") < 0 )
 {
  printk( KERN_INFO "Can`t register device\n" );
  return -1;
 }
 
 
 printk( KERN_INFO "--class_create()-- start vk3344_number = %d--\r\n", vk3344_number );
 printk( KERN_INFO "--vk3344_number = %d--MAJOR=%d--MINOR=%d--\r\n", vk3344_number, MAJOR(vk3344_number),
MINOR(vk3344_number) );
 printk( KERN_INFO "--MAKDEV=%d-- vk3344_number=%d--\r\n", MKDEV( MAJOR(vk3344_number), 0 ), MKDEV( MAJOR
(vk3344_number), MINOR(vk3344_number) ));
 
 
 vk3344_class = class_create( THIS_MODULE, "vk3344" );
 
  if (IS_ERR(vk3344_class)) {
   printk( KERN_INFO "--class_create()--error()\n");
   return -1;
  }
 
 cdev_init( &p_bank->dev, &vk3344_fops );
 strlcpy( p_bank->name, DEVICE_NAME, 6 );
 kobject_set_name(&p_bank->dev.kobj, p_bank->name);
 p_bank->dev.owner = THIS_MODULE;
 p_bank->dev.ops = &vk3344_fops;
  
 printk( KERN_INFO "--cdev_add()-- start--\r\n" );
 if ( cdev_add( &(p_bank->dev), vk3344_number, 1 ) )
 {
  kfree( p_bank );
  printk( KERN_INFO "cdev_add() error\r\n" );
  return 1;
 }
 
 printk( KERN_INFO "--device_create()-- start--\r\n" );
 device_create( vk3344_class, NULL, MKDEV( MAJOR(vk3344_number), 0 ), NULL, "vk3344" );
 printk( KERN_INFO "--device_create()-- end--\r\n" );
 printk( KERN_INFO "-----vk3344 driver initialized.------\r\n" );
 
 i2c_add_driver( &vk3344_driver );
 return 0;
}
static void __exit vk3344_exit(void)
{
 i2c_del_driver(&vk3344_driver);
 cdev_del( &p_bank->dev );
 unregister_chrdev_region( vk3344_number, 1 );
 //class_device_destroy( vk3344_class, vk334_number );
 class_destroy(vk3344_class);
 kfree( p_bank );
 return;
}
 
MODULE_DESCRIPTION("vk3344 /dev entries driver");
MODULE_LICENSE("GPL");
module_init(vk3344_init);
module_exit(vk3344_exit);
阅读(1264) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~