IIC Device(At24c02) Driver for Linux2.6.xx+ARM9

来源:互联网 发布:出售一审淘宝店铺 编辑:程序博客网 时间:2024/05/21 10:35

/* iic-dev: at24c02 256bytes(2k bits)
  * From 2013-01-31 To 2013-02-02
  */

----------------------------------------------------------driver---------------------------------------------------------------

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
//begin
#include <linux/fs.h>
//error: variable `at24c02_operations' has initializer but incomplete type
//end
//begin
//czat24c02_iicdev: Unknown symbol copy_from_user
#include <asm/uaccess.h>
//end
static unsigned short ignore[] = { I2C_CLIENT_END };
static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END };

static int major;
static struct class *at24c02_cls;
static struct class_device *at24c02_cls_dev;
static struct i2c_client *new_client;


static struct i2c_client_address_data addr_data = {
 .normal_i2c = normal_addr,
 .probe = ignore,
 .ignore = ignore,
};

static struct bin_attribute at24c02_attr = {
 .attr = {
  .name = "at24c02",
  .mode = S_IRUGO,
  .owner = THIS_MODULE,
 },
 //.size = EEPROM_SIZE,
 //.read = eeprom_read,
};

static int czat24c02_attach_adapter(struct i2c_adapter *adapter);
static int czat24c02_detach_client(struct i2c_client *client);


static struct i2c_driver at24c02_driver = {
 .driver = {
  .name = "at24c02",
 },
 //.id  = I2C_DRIVERID_EEPROM,
 .attach_adapter = czat24c02_attach_adapter,
 .detach_client = czat24c02_detach_client,
};

static ssize_t czat24c02_read (struct file *file, char __user *buffer, size_t size, loff_t *ppos)
{
 printk("driver: czat24c02_read in ok\n");
 if (size != 1)
       printk("driver: czat24c02_read size != 1\n");

 struct i2c_msg msg[2];
 unsigned char val; //val[1]:addr for reading
 unsigned char data;
 
 copy_from_user(&val, buffer, 1);//get the addr for reading
 printk("driver: czat24c02_read copy_from_user ok\n");

 msg[0].addr = 0x50; //at24c02 address
 msg[0].buf = &val;
 msg[0].len = 1;
 msg[0].flags = 0; //write addr

 msg[1].addr = 0x50; //at24c02 address
 msg[1].buf = &data;//get the data
 msg[1].len = 1;
 msg[1].flags = I2C_M_RD; //read addr

 if((i2c_transfer(new_client->adapter, msg, 2))==2)
  {
   printk("driver: czat24c02_read i2c_transfer=2 ok\n");
   copy_to_user(buffer,&data,1);//tell app what we got
   printk("driver: czat24c02_read copy_to_user ok\n");
   return 0;
  }
 printk("driver: czat24c02_read i2c_transfer !!!!=2\n");

 return -EIO;

}

static int czat24c02_write (struct file *file, const char __user *buffer, size_t size, loff_t *ppos)
{
 printk("driver: czat24c02_write in ok\n");

 struct i2c_msg msg[1];
 unsigned char val[2]; //val[1]:addr for writing, val[2]:data for writing
 
 copy_from_user(val, buffer, 2);
 printk("driver: czat24c02_write addr:%d, data:%d\n",val[0],val[1]);

 msg[0].addr = 0x50; //at24c02 address
 msg[0].buf = val;
 msg[0].len = 2;
 msg[0].flags = 0; //write msg
 
 i2c_transfer(new_client->adapter, msg, 1);
 
 return 0;
}

static int czat24c02_open(struct inode *inode, struct file *file)
{
 printk("driver: czat24c02_open in ok\n");

 return 0;
}

static struct file_operations at24c02_operations = {
 .owner = THIS_MODULE,
 .open = czat24c02_open,
 .read   = czat24c02_read,
 .write  = czat24c02_write,
};

static int czat24c02_detect(struct i2c_adapter *adapter, int address, int kind)
{
 printk("driver: czat24c02_detect in ok\n");

 i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA
       | I2C_FUNC_SMBUS_BYTE);
 new_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);

 new_client->addr = address;
 new_client->adapter = adapter;
 new_client->driver = &at24c02_driver;
 new_client->flags = 0;
 
 strlcpy(new_client->name, "at24c02", I2C_NAME_SIZE);

 i2c_attach_client(new_client);

 sysfs_create_bin_file(&new_client->dev.kobj, &at24c02_attr);

 major = register_chrdev(0, "at24c02", &at24c02_operations);
 at24c02_cls = class_create(THIS_MODULE, "at24c02_cls");
 at24c02_cls_dev = class_device_create(at24c02_cls, NULL, MKDEV(major,0), NULL, "at24c02_cls_dev");

 return 0;
}

static int czat24c02_detach_client(struct i2c_client *client)
{
 printk("driver: czat24c02_detach_client in ok\n");

 int err;

 sysfs_remove_bin_file(&client->dev.kobj, &at24c02_attr);

 err = i2c_detach_client(client);
 if (err)
  return err;

 kfree(i2c_get_clientdata(client));
 
 class_device_destroy(at24c02_cls, MKDEV(major,0));
 class_destroy(at24c02_cls);
 unregister_chrdev(major, "at24c02");

 return 0;
}

static int czat24c02_attach_adapter(struct i2c_adapter *adapter)
{
 printk("driver: czat24c02_attach_adapter in ok\n");

 return i2c_probe(adapter, &addr_data, czat24c02_detect);
}

static int __init czat24c02_init(void)
{
 printk("driver: czat24c02_init in ok\n");

 i2c_add_driver(&at24c02_driver);

 return 0;
}

static void __exit czat24c02_exit(void)
{
 printk("driver: czat24c02_exit in ok\n");

 i2c_del_driver(&at24c02_driver);

}

module_init(czat24c02_init);
module_exit(czat24c02_exit);
MODULE_AUTHOR("chaozang(cz) <zangchao.cn@gmail.com>,copy frm my teacher:weidongshan,thanks so much!");
MODULE_LICENSE("GPL");

----------------------------------------------------test app----------------------------------------------------------

/*
  *  read: at24c02 addr
  * write: at24c02 addr data
 */
#include <sys/types.h>
#include <sys/stat.h>

#include <fcntl.h>
#include <stdio.h>

void print_usage(char *file)
{
 printf(" read: %s addr\n",file);
 printf("write: %s addr data\n",file);
}

//char *argv[ ] == char **argv
int main(int argc, char **argv)
{
 int fd;

 unsigned char buffer[2];
 
 if((argc != 2)&&(argc != 3))
  print_usage(argv[0]);

 fd = open("/dev/at24c02_cls_dev",O_RDWR);
 if (fd < 0)
 {
  printf("can't open /dev/at24c02_cls_dev\n");
  return -1;
 }
 
 //if (strcmp(argv[1], "r") == 0)
 if(argc == 2)
  {
      printf("app: argc == 2\n");
   buffer[0] = strtoul(argv[1], NULL, 0);
   printf("app: buffer[0] is %d\n",buffer[0]);
   read(fd, buffer, 1);
   printf("app: read result is:%d\n",buffer[0]);
   //begin
   //printf("app: read result is:%s\n",buffer[0]);
   //Segmentation fault
   //end
   
  }
 else if(argc == 3)
  {

   buffer[0] = strtoul(argv[1], NULL, 0);
   buffer[1] = strtoul(argv[2], NULL, 0);
   write(fd, buffer, 2);
  }
 else
  {
   print_usage(argv[0]);
   return -1;
  }
 
 return 0;
}

-----------------------------------------------------------

Contact: zangchao.cn@gmail.com

原创粉丝点击