在Android源码树中添加userspace I2C读写工具

通过/dev/i2c-n节点,用户可以在userspace直接访问板上的i2c外设寄存器,主要是透过I2C_RDWR这个IO控制命令将i2c_msg数组传递给kernel去执行。下面的代码可以完成这个功能:

[cpp] view plain copy
  1. #include <stdio.h>  
  2. #include <linux/types.h>  
  3. #include <fcntl.h>  
  4. #include <unistd.h>  
  5. #include <stdlib.h>  
  6. #include <sys/types.h>  
  7. #include <sys/ioctl.h>  
  8. #include <errno.h>  
  9. #include <assert.h>  
  10. #include <string.h>  
  11. #include <linux/i2c.h>  
  12.   
  13. /* This is the structure as used in the I2C_RDWR ioctl call */  
  14. struct i2c_rdwr_ioctl_data {  
  15.         struct i2c_msg __user *msgs;    /* pointers to i2c_msgs */  
  16.         __u32 nmsgs;                    /* number of i2c_msgs */  
  17. };  
  18.   
  19. int i2c_read_reg(char *dev, unsigned char *buf, unsigned slave_address, unsigned reg_address, int len)  
  20. {  
  21.     struct i2c_rdwr_ioctl_data work_queue;  
  22.     unsigned char w_val = reg_address;  
  23.     int ret;  
  24.   
  25.     int fd = open(dev, O_RDWR);  
  26.     if (!fd) {  
  27.         printf("Error on opening the device file\n");  
  28.         return 0;  
  29.     }  
  30.   
  31.     work_queue.nmsgs = 2;  
  32.     work_queue.msgs = (struct i2c_msg*)malloc(work_queue.nmsgs *sizeof(struct  
  33.             i2c_msg));  
  34.     if (!work_queue.msgs) {  
  35.         printf("Memory alloc error\n");  
  36.         close(fd);  
  37.         return 0;  
  38.     }  
  39.   
  40.     ioctl(fd, I2C_TIMEOUT, 2);  
  41.     ioctl(fd, I2C_RETRIES, 1);  
  42.   
  43.     (work_queue.msgs[0]).len = 1;  
  44.     (work_queue.msgs[0]).addr = slave_address;  
  45.     (work_queue.msgs[0]).buf = &w_val;  
  46.   
  47.     (work_queue.msgs[1]).len = len;  
  48.     (work_queue.msgs[1]).flags = I2C_M_RD;  
  49.     (work_queue.msgs[1]).addr = slave_address;  
  50.     (work_queue.msgs[1]).buf = buf;  
  51.   
  52.     ret = ioctl(fd, I2C_RDWR, (unsigned long) &work_queue);  
  53.     if (ret < 0) {  
  54.         printf("Error during I2C_RDWR ioctl with error code: %d\n", ret);  
  55.         close(fd);  
  56.         free(work_queue.msgs);  
  57.         return 0;  
  58.     } else {  
  59.         printf("read salve:%02x reg:%02x\n", slave_address, reg_address);  
  60.         close(fd);  
  61.         free(work_queue.msgs);  
  62.         return len;  
  63.     }  
  64. }  
  65.   
  66. int i2c_write_reg(char *dev, unsigned char *buf, unsigned slave_address, unsigned reg_address, int len)  
  67. {  
  68.     struct i2c_rdwr_ioctl_data work_queue;  
  69.     unsigned char w_val = reg_address;  
  70.     unsigned char w_buf[len+1];  
  71.     int ret;  
  72.   
  73.     w_buf[0] = reg_address;  
  74.   
  75.     int fd = open(dev, O_RDWR);  
  76.     if (!fd) {  
  77.         printf("Error on opening the device file\n");  
  78.         return 0;  
  79.     }  
  80.   
  81.     work_queue.nmsgs = 1;  
  82.     work_queue.msgs = (struct i2c_msg*)malloc(work_queue.nmsgs *sizeof(struct  
  83.             i2c_msg));  
  84.     if (!work_queue.msgs) {  
  85.         printf("Memory alloc error\n");  
  86.         close(fd);  
  87.         return 0;  
  88.     }  
  89.   
  90.     ioctl(fd, I2C_TIMEOUT, 2);  
  91.     ioctl(fd, I2C_RETRIES, 1);  
  92.   
  93.     (work_queue.msgs[0]).len = 1 + len;  
  94.     (work_queue.msgs[0]).addr = slave_address;  
  95.     (work_queue.msgs[0]).buf = w_buf;  
  96.   
  97.     memcpy(w_buf + 1, buf, len);  
  98.   
  99.     ret = ioctl(fd, I2C_RDWR, (unsigned long) &work_queue);  
  100.     if (ret < 0) {  
  101.         printf("Error during I2C_RDWR ioctl with error code: %d\n", ret);  
  102.         close(fd);  
  103.         free(work_queue.msgs);  
  104.         return 0;  
  105.     } else {  
  106.         printf("write salve:%02x reg:%02x\n", slave_address, reg_address);  
  107.         close(fd);  
  108.         free(work_queue.msgs);  
  109.         return len;  
  110.     }  
  111. }  
  112.   
  113. int main(int argc, char **argv)  
  114. {  
  115.     unsigned int fd;  
  116.     unsigned int slave_address, reg_address;  
  117.     unsigned r_w;  
  118.     unsigned w_val;  
  119.     unsigned char rw_val;  
  120.   
  121.     if (argc < 5) {  
  122.         printf("Usage:\n%s /dev/i2c-x start_addr reg_addr rw[0|1] [write_val]\n", argv[0]);  
  123.         return 0;  
  124.     }  
  125.   
  126.     fd = open(argv[1], O_RDWR);  
  127.   
  128.     if (!fd) {  
  129.         printf("Error on opening the device file %s\n", argv[1]);  
  130.         return 0;  
  131.     }  
  132.   
  133.     sscanf(argv[2], "%x", &slave_address);  
  134.     sscanf(argv[3], "%x", ®_address);  
  135.     sscanf(argv[4], "%d", &r_w);  
  136.   
  137.     if (r_w == 0) {  
  138.         i2c_read_reg(argv[1], &rw_val, slave_address, reg_address, 1);  
  139.         printf("Read %s-%x reg %x, read value:%x\n", argv[1], slave_address, reg_address, rw_val);  
  140.     } else {  
  141.         if (argc < 6) {  
  142.             printf("Usage:\n%s /dev/i2c-x start_addr reg_addr r|w[0|1] [write_val]\n", argv[0]);  
  143.             return 0;  
  144.         }  
  145.         sscanf(argv[5], "%d", &w_val);  
  146.         if ((w_val & ~0xff) != 0)  
  147.             printf("Error on written value %s\n", argv[5]);  
  148.   
  149.         rw_val = (unsigned char)w_val;  
  150.         i2c_write_reg(argv[1], &rw_val, slave_address, reg_address, 1);  
  151.     }  
  152.   
  153.     return 0;  
  154. }  

在android/external/新建i2c-util目录,上述源代码存入android/external/i2c-util/i2c-util.c,编写对应的Android.mk:

[plain] view plain copy
  1. LOCAL_PATH := $(call my-dir)  
  2. include $(CLEAR_VARS)  
  3.   
  4. LOCAL_MODULE_TAGS := optional  
  5.   
  6. LOCAL_MODULE := i2c-util  
  7.   
  8. LOCAL_SRC_FILES += \  
  9.     i2c-util.c \  
  10.   
  11. include $(BUILD_EXECUTABLE) 

以下我改过后能用:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_C_INCLUDES :=

LOCAL_CFLAGS := -O3

LOCAL_SRC_FILES += i2c-util.c


LOCAL_SHARED_LIBRARIES := liblog libGLESv2

LOCAL_MODULE_TAGS := optional

LOCAL_MODULE := i2c-util  
include $(BUILD_EXECUTABLE) 




编译Android后,上述工具会位于/system/bin目录。在电路板上使用它:

[plain] view plain copy
  1. / #  i2c-rw /dev/i2c-2 0x38 0x1 0    
  2. read salve:38 reg:01 value:12    
  3. / #     
  4. / #  i2c-rw /dev/i2c-2 0x38 0x2 0    
  5. read salve:38 reg:02 value:81   

你可能感兴趣的:(在Android源码树中添加userspace I2C读写工具)