zoukankan      html  css  js  c++  java
  • 驱动13.i2c设备驱动程序

    1 分析i2c设备的识别过程
    i2c_add_driver
        i2c_register_driver
            driver->driver.bus = &i2c_bus_type;
            driver_register(&driver->driver);
            
            list_for_each_entry(adapter, &adapters, list) {
                driver->attach_adapter(adapter);
                            i2c_probe(adapter, &addr_data, eeprom_detect);
                                i2c_probe_address // 发出S信号,发出设备地址(来自addr_data)
                                    i2c_smbus_xfer
                                        i2c_smbus_xfer_emulated
                                            i2c_transfer
                                                adap->algo->master_xfer // s3c24xx_i2c_xfer
                                                
            
    2 怎么写I2C设备驱动程序?
    2.1 分配一个i2c_driver结构体
    2.2 设置
          attach_adapter // 它直接调用 i2c_probe(adap, 设备地址, 发现这个设备后要调用的函数);
          detach_client  // 卸载这个驱动后,如果之前发现能够支持的设备,则调用它来清理
          
    2.3 注册:i2c_add_driver

    3 写代码

      1 #include <linux/kernel.h>
      2 #include <linux/init.h>
      3 #include <linux/module.h>
      4 #include <linux/slab.h>
      5 #include <linux/jiffies.h>
      6 #include <linux/i2c.h>
      7 #include <linux/mutex.h>
      8 #include <linux/fs.h>
      9 #include <asm/uaccess.h>
     10 
     11 static unsigned short ignore[]      = { I2C_CLIENT_END };
     12 static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END }; /* 地址值是7位 */
     13                                         /* 改为0x60的话, 由于不存在设备地址为0x60的设备, 所以at24cxx_detect不被调用 */
     14 
     15 static unsigned short force_addr[] = {ANY_I2C_BUS, 0x60, I2C_CLIENT_END};
     16 static unsigned short * forces[] = {force_addr, NULL};
     17                                         
     18 static struct i2c_client_address_data addr_data = {
     19     .normal_i2c    = normal_addr,  /* 要发出S信号和设备地址并得到ACK信号,才能确定存在这个设备 */
     20     .probe        = ignore,
     21     .ignore        = ignore,
     22     //.forces     = forces, /* 强制认为存在这个设备 */
     23 };
     24 
     25 static struct i2c_driver at24cxx_driver;
     26 
     27 
     28 static int major;
     29 static struct class *cls;
     30 struct i2c_client *at24cxx_client;
     31 
     32 static ssize_t at24cxx_read(struct file *file, char __user *buf, size_t size, loff_t * offset)
     33 {
     34     unsigned char address;
     35     unsigned char data;
     36     struct i2c_msg msg[2];
     37     int ret;
     38     
     39     /* address = buf[0] 
     40      * data    = buf[1]
     41      */
     42     if (size != 1)
     43         return -EINVAL;
     44     
     45     copy_from_user(&address, buf, 1);
     46 
     47     /* 数据传输三要素: 源,目的,长度 */
     48 
     49     /* 读AT24CXX时,要先把要读的存储空间的地址发给它 */
     50     msg[0].addr  = at24cxx_client->addr;  /* 目的 */
     51     msg[0].buf   = &address;              /**/
     52     msg[0].len   = 1;                     /* 地址=1 byte */
     53     msg[0].flags = 0;                     /* 表示写 */
     54 
     55     /* 然后启动读操作 */
     56     msg[1].addr  = at24cxx_client->addr;  /**/
     57     msg[1].buf   = &data;                 /* 目的 */
     58     msg[1].len   = 1;                     /* 数据=1 byte */
     59     msg[1].flags = I2C_M_RD;                     /* 表示读 */
     60 
     61 
     62     ret = i2c_transfer(at24cxx_client->adapter, msg, 2);
     63     if (ret == 2)
     64     {
     65         copy_to_user(buf, &data, 1);
     66         return 1;
     67     }
     68     else
     69         return -EIO;
     70 }
     71 
     72 static ssize_t at24cxx_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
     73 {
     74     unsigned char val[2];
     75     struct i2c_msg msg[1];
     76     int ret;
     77     
     78     /* address = buf[0] 
     79      * data    = buf[1]
     80      */
     81     if (size != 2)
     82         return -EINVAL;
     83     
     84     copy_from_user(val, buf, 2);
     85 
     86     /* 数据传输三要素: 源,目的,长度 */
     87     msg[0].addr  = at24cxx_client->addr;  /* 目的 */
     88     msg[0].buf   = val;                   /**/
     89     msg[0].len   = 2;                     /* 地址+数据=2 byte */
     90     msg[0].flags = 0;                     /* 表示写 */
     91 
     92     ret = i2c_transfer(at24cxx_client->adapter, msg, 1);
     93     if (ret == 1)
     94         return 2;
     95     else
     96         return -EIO;
     97 }
     98 
     99 
    100 static struct file_operations at24cxx_fops = {
    101     .owner = THIS_MODULE,
    102     .read  = at24cxx_read,
    103     .write = at24cxx_write,
    104 };
    105 
    106 static int at24cxx_detect(struct i2c_adapter *adapter, int address, int kind)
    107 {    
    108     printk("at24cxx_detect
    ");
    109 
    110     /* 构构一个i2c_client结构体: 以后收改数据时会用到它 */
    111     at24cxx_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
    112     at24cxx_client->addr    = address;
    113     at24cxx_client->adapter = adapter;
    114     at24cxx_client->driver  = &at24cxx_driver;
    115     strcpy(at24cxx_client->name, "at24cxx");
    116     i2c_attach_client(at24cxx_client);
    117     
    118     major = register_chrdev(0, "at24cxx", &at24cxx_fops);
    119 
    120     cls = class_create(THIS_MODULE, "at24cxx");
    121     class_device_create(cls, NULL, MKDEV(major, 0), NULL, "at24cxx"); /* /dev/at24cxx */
    122     
    123     return 0;
    124 }
    125 
    126 static int at24cxx_attach(struct i2c_adapter *adapter)
    127 {
    128     return i2c_probe(adapter, &addr_data, at24cxx_detect);
    129 }
    130 
    131 static int at24cxx_detach(struct i2c_client *client)
    132 {
    133     printk("at24cxx_detach
    ");
    134     class_device_destroy(cls, MKDEV(major, 0));
    135     class_destroy(cls);
    136     unregister_chrdev(major, "at24cxx");
    137 
    138     i2c_detach_client(client);
    139     kfree(i2c_get_clientdata(client));
    140 
    141     return 0;
    142 }
    143 
    144 
    145 /* 1. 分配一个i2c_driver结构体 */
    146 /* 2. 设置i2c_driver结构体 */
    147 static struct i2c_driver at24cxx_driver = {
    148     .driver = {
    149         .name    = "at24cxx",
    150     },
    151     .attach_adapter = at24cxx_attach,
    152     .detach_client  = at24cxx_detach,
    153 };
    154 
    155 static int at24cxx_init(void)
    156 {
    157     i2c_add_driver(&at24cxx_driver);
    158     return 0;
    159 }
    160 
    161 static void at24cxx_exit(void)
    162 {
    163     i2c_del_driver(&at24cxx_driver);
    164 }
    165 
    166 module_init(at24cxx_init);
    167 module_exit(at24cxx_exit);
    168 
    169 MODULE_LICENSE("GPL");
    i2c设备驱动程序
  • 相关阅读:
    Ubuntu adb devices :???????????? no permissions (verify udev rules) 解决方法
    ubuntu 关闭显示器的命令
    ubuntu android studio kvm
    ubuntu 14.04版本更改文件夹背景色为草绿色
    ubuntu 创建桌面快捷方式
    Ubuntu 如何更改用户密码
    ubuntu 14.04 返回到经典桌面方法
    ubuntu 信使(iptux) 创建桌面快捷方式
    Eclipse failed to get the required ADT version number from the sdk
    Eclipse '<>' operator is not allowed for source level below 1.7
  • 原文地址:https://www.cnblogs.com/Lwd-linux/p/6358158.html
Copyright © 2011-2022 走看看