在Android源码树中添加userspace I2C读写工具(i2c-util)

简介:

by LiAnLab.org / 宋宝华

通过/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)  

编译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    

 本文转自 21cnbao 51CTO博客,原文链接:http://blog.51cto.com/21cnbao/976137 ,如需转载请自行联系原作者


相关文章
|
3月前
|
Ubuntu 开发工具 Android开发
Repo下载AOSP源码:基于ubuntu22.04 环境配置,android-12.0.0_r32
本文介绍了在基于Ubuntu 22.04的环境下配置Python 3.9、安装repo工具、下载和同步AOSP源码包以及处理repo同步错误的详细步骤。
244 0
Repo下载AOSP源码:基于ubuntu22.04 环境配置,android-12.0.0_r32
|
3月前
|
编解码 Android开发
【Android Studio】使用UI工具绘制,ConstraintLayout 限制性布局,快速上手
本文介绍了Android Studio中使用ConstraintLayout布局的方法,通过创建布局文件、设置控件约束等步骤,快速上手UI设计,并提供了一个TV Launcher界面布局的绘制示例。
59 1
|
3月前
|
开发工具 git 索引
repo sync 更新源码 android-12.0.0_r34, fatal: 不能重置索引文件至版本 ‘v2.27^0‘。
本文描述了在更新AOSP 12源码时遇到的repo同步错误,并提供了通过手动git pull更新repo工具来解决这一问题的方法。
132 1
|
3月前
|
开发工具 uml git
AOSP源码下载方法,解决repo sync错误:android-13.0.0_r82
本文分享了下载AOSP源码的方法,包括如何使用repo工具和处理常见的repo sync错误,以及配置Python环境以确保顺利同步特定版本的AOSP代码。
474 0
AOSP源码下载方法,解决repo sync错误:android-13.0.0_r82
|
3月前
|
Java Android开发 芯片
使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题
本文介绍了如何将基于全志H713芯片的AOSP Android源码导入Android Studio以解决编译和编码问题,通过操作步骤的详细说明,展示了在Android Studio中利用代码提示和补全功能快速定位并修复编译错误的方法。
143 0
使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题
|
3月前
|
Android开发
我的Android 进阶修炼(1): AOSP源码根目录结构
本文介绍了AOSP源码的根目录结构,提供了基于MTK9269 Android 9.0源码的目录说明,帮助读者了解AOSP源码的组织方式和各目录的功能。
189 0
我的Android 进阶修炼(1): AOSP源码根目录结构
|
3月前
|
开发工具 Android开发 git
全志H713 Android 11 :给AOSP源码,新增一个Product
本文介绍了在全志H713 Android 11平台上新增名为myboard的产品的步骤,包括创建新的device目录、编辑配置文件、新增内核配置、记录差异列表以及编译kernel和Android系统的详细过程。
133 0
|
3月前
|
Ubuntu 开发工具 Android开发
Repo下载、编译AOSP源码:基于Ubuntu 21.04,android-12.1.0_r27
文章记录了作者在Ubuntu 21.04服务器上配置环境、下载并编译基于Android 12.1.0_r27版本的AOSP源码的过程,包括解决编译过程中遇到的问题和错误处理方法。
206 0
|
Android开发
【Android 逆向】Android 逆向通用工具开发 ( Android 平台运行的 cmd 程序类型 | Android 平台运行的 cmd 程序编译选项 | 编译 cmd 可执行程序 )(二)
【Android 逆向】Android 逆向通用工具开发 ( Android 平台运行的 cmd 程序类型 | Android 平台运行的 cmd 程序编译选项 | 编译 cmd 可执行程序 )(二)
167 0
【Android 逆向】Android 逆向通用工具开发 ( Android 平台运行的 cmd 程序类型 | Android 平台运行的 cmd 程序编译选项 | 编译 cmd 可执行程序 )(二)
|
移动开发 Android开发 C++
【Android 逆向】Android 逆向通用工具开发 ( Android 平台运行的 cmd 程序类型 | Android 平台运行的 cmd 程序编译选项 | 编译 cmd 可执行程序 )(一)
【Android 逆向】Android 逆向通用工具开发 ( Android 平台运行的 cmd 程序类型 | Android 平台运行的 cmd 程序编译选项 | 编译 cmd 可执行程序 )(一)
148 0
【Android 逆向】Android 逆向通用工具开发 ( Android 平台运行的 cmd 程序类型 | Android 平台运行的 cmd 程序编译选项 | 编译 cmd 可执行程序 )(一)
下一篇
无影云桌面