Linux 驱动——IIC(AT24C02)

at24c02_drv.c文件:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>

#define DEVICE_NAME "at24c02"
#define DRIVER_NAME "at24c02_drv"

static i2c_client *at24c02_client;

int major;

struct class *at24c02dev_class;
struct class_device *at24c02dev_class_device;

static unsigned short ignore[] = {I2C_CLIENT_END};
static unsigned short normal_addr[] = {0x50, I2C_CLIENT_END};

static ssize_t at24c02_drv_read(struct file *file, char __user *userbuf, size_t count, loff_t *off)
{
  struct i2c_msg msg[2];
  u8 addr, data;
  int ret;

  cpoy_from_user(&addr, userbuf, 1);

  msg[0].addr = at24c02_client->addr;
  msg[0].flags = 0;                   //写标志
  msg[0].len = 1;
  msg[0].buf = &addr                  //写入要读的地址

  msg[1].addr = at24c02_client->addr;
  msg[1].flags = I2C_M_RD;            //读标志
  msg[1].len = 1;
  msg[1].buf = &data                  //读出数据

  ret = i2c_transfer(at24c02_client->adapter, msg, 2);

  if(ret == 2)                        //表示2msg传输成功
  {
    copy_to_user(buf, &data, 1);     //上传数据
    return 0;
  }
  else
  return -EAGAIN;
}

 

static ssize_t at24c02_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
  struct i2c_msg msg[1];
  u8 addr_and_data[2];
  int ret;

  copy_from_user(addr_and_data, buf, 2);    //获取 地址 数据

  msg[0].addr = at24c02_client->addr;
  msg[0].flags = 0;                         //写标志
  msg[0].len = 2;
  msg[0].buf = addr_and_data;               //写入要写的地址和数据

  ret = i2c_transfer(at24c02_client->adapter, msg, 1);

  if(ret == 1)                              //表示1msg传输成功
    return 0;
  else
    return -EAGAIN;
}

struct file_operations at24c02_drv_fops = {
  .owner = THIS_MODULE,
  .read = at24c02_drv_read,
  .write = at24c02_drv_write,
};

 

struct i2c_client_address_data at24c02_addr = {
  .normal_i2c = normal_addr;   //存放正常的设备高7位地址数据
  .probe = ignore;             //存放不受*ignore影响的高7位设备地址数据
  .ignore = ignore;            //存放*ignore的高7位设备地址数据
};

 

static i2c_driver at24c02_driver = {
  .driver = {
    .name = "at24c02",
  },
  .id = I2C_DRIVERID_EEPROM,
  .attach_adapter = at24c02_attach_adapter,
  .detach_client = at24c02_detach_client,
};

 

static int at24c02_detach_client(struct i2c_client *client)
{
  i2c_detach_client(at24c02_client);
  kfree(at24c02_client);
  class_device_destory(at24c02dev_class, MKDEV(major, 0));
  class_destory(at24c02dev_class);
  return 0;
}

 

//注册真正地IIC设备
static int at24c02_detect(struct i2c_adapter *adap, int addr, int kind)
{
  //分配并初始化i2c_client结构体
  at24c02_client = kzalloc(sizeof(i2c_adapter *adap), GFP_KERNEL);
  at24c02_client->addr = addr;
  at24c02_client->adapter = adap;
  at24c02_client->driver = &at24c02_driver
  at24c02_client->flags = 0;
  strlcpy(at24c02_client->name, DEVICE_NAME, I2C_NAME_SIZE);       //设置IIC设备的名字

  //将at24c02_client与适配器进行连接
  i2c_attach_client(at24c02_client);

  //注册字符类设备
  major = regeister_chrdev(0, DEVICE_NAME, &at24c02_drv_fops);     //注册字符设备
  at24c02dev_class = class_create(THID_MODULE, DEVICE_NAME);       //注册设备类
  at24c02dev_class_device = class_device_create(at24c02dev_class, NULL, MKEDV(major, 0), NULL, DEVICE_NAME);
}

//发送IIC设备的地址at24c02_addr, 如果有响应则调用回调函数at24c02_detect
static int at24c02_attach_adapter(struct i2c_adapter *adapter)
{
  return i2c_probe(adapter, &at24c02_addr, at24c02_detect);
}

static int at24c02_drv_init()
{
  i2c_add_driver(&at24c02_driver);
  return 0;
}

static void at24c02_drv_exit()
{
  i2c_del_driver(&at24c02_driver);
} 

module_init(at24c02_drv_init);
module_exit(at24c02_drv_exit);

MODULE_LICENSE("GPL");

 

猜你喜欢

转载自www.cnblogs.com/lian-meng/p/10818192.html