在Android源码树中添加userspace I2C读写工具(i2c-util)
by LiAnLab.org / 宋宝华 通过/dev/i2c-n节点,用户可以在userspace直接访问板上的i2c外设寄存器,主要是透过I2C_RDWR这个IO控制命令将i2c_msg数组传递给kernel去执行。下面的代码可以完成这个功能: [cpp] view plain copy #include<stdio.h> #include<linux/types.h> #include<fcntl.h> #include<unistd.h> #include<stdlib.h> #include<sys/types.h> #include<sys/ioctl.h> #include<errno.h> #include<assert.h> #include<string.h> #include<linux/i2c.h> /*ThisisthestructureasusedintheI2C_RDWRioctlcall*/ structi2c_rdwr_ioctl_data{ structi2c_msg__user*msgs;/*pointerstoi2c_msgs*/ __u32nmsgs;/*numberofi2c_msgs*/ }; inti2c_read_reg(char*dev,unsignedchar*buf,unsignedslave_address,unsignedreg_address,intlen) { structi2c_rdwr_ioctl_datawork_queue; unsignedcharw_val=reg_address; intret; intfd=open(dev,O_RDWR); if(!fd){ printf("Erroronopeningthedevicefile\n"); return0; } work_queue.nmsgs=2; work_queue.msgs=(structi2c_msg*)malloc(work_queue.nmsgs*sizeof(struct i2c_msg)); if(!work_queue.msgs){ printf("Memoryallocerror\n"); close(fd); return0; } ioctl(fd,I2C_TIMEOUT,2); ioctl(fd,I2C_RETRIES,1); (work_queue.msgs[0]).len=1; (work_queue.msgs[0]).addr=slave_address; (work_queue.msgs[0]).buf=&w_val; (work_queue.msgs[1]).len=len; (work_queue.msgs[1]).flags=I2C_M_RD; (work_queue.msgs[1]).addr=slave_address; (work_queue.msgs[1]).buf=buf; ret=ioctl(fd,I2C_RDWR,(unsignedlong)&work_queue); if(ret<0){ printf("ErrorduringI2C_RDWRioctlwitherrorcode:%d\n",ret); close(fd); free(work_queue.msgs); return0; }else{ printf("readsalve:%02xreg:%02x\n",slave_address,reg_address); close(fd); free(work_queue.msgs); returnlen; } } inti2c_write_reg(char*dev,unsignedchar*buf,unsignedslave_address,unsignedreg_address,intlen) { structi2c_rdwr_ioctl_datawork_queue; unsignedcharw_val=reg_address; unsignedcharw_buf[len+1]; intret; w_buf[0]=reg_address; intfd=open(dev,O_RDWR); if(!fd){ printf("Erroronopeningthedevicefile\n"); return0; } work_queue.nmsgs=1; work_queue.msgs=(structi2c_msg*)malloc(work_queue.nmsgs*sizeof(struct i2c_msg)); if(!work_queue.msgs){ printf("Memoryallocerror\n"); close(fd); return0; } ioctl(fd,I2C_TIMEOUT,2); ioctl(fd,I2C_RETRIES,1); (work_queue.msgs[0]).len=1+len; (work_queue.msgs[0]).addr=slave_address; (work_queue.msgs[0]).buf=w_buf; memcpy(w_buf+1,buf,len); ret=ioctl(fd,I2C_RDWR,(unsignedlong)&work_queue); if(ret<0){ printf("ErrorduringI2C_RDWRioctlwitherrorcode:%d\n",ret); close(fd); free(work_queue.msgs); return0; }else{ printf("writesalve:%02xreg:%02x\n",slave_address,reg_address); close(fd); free(work_queue.msgs); returnlen; } } intmain(intargc,char**argv) { unsignedintfd; unsignedintslave_address,reg_address; unsignedr_w; unsignedw_val; unsignedcharrw_val; if(argc<5){ printf("Usage:\n%s/dev/i2c-xstart_addrreg_addrrw[0|1][write_val]\n",argv[0]); return0; } fd=open(argv[1],O_RDWR); if(!fd){ printf("Erroronopeningthedevicefile%s\n",argv[1]); return0; } sscanf(argv[2],"%x",&slave_address); sscanf(argv[3],"%x",®_address); sscanf(argv[4],"%d",&r_w); if(r_w==0){ i2c_read_reg(argv[1],&rw_val,slave_address,reg_address,1); printf("Read%s-%xreg%x,readvalue:%x\n",argv[1],slave_address,reg_address,rw_val); }else{ if(argc<6){ printf("Usage:\n%s/dev/i2c-xstart_addrreg_addrr|w[0|1][write_val]\n",argv[0]); return0; } sscanf(argv[5],"%d",&w_val); if((w_val&~0xff)!=0) printf("Erroronwrittenvalue%s\n",argv[5]); rw_val=(unsignedchar)w_val; i2c_write_reg(argv[1],&rw_val,slave_address,reg_address,1); } return0; } 在android/external/新建i2c-util目录,上述源代码存入android/external/i2c-util/i2c-util.c,编写对应的Android.mk: [plain] view plain copy LOCAL_PATH:=$(callmy-dir) include$(CLEAR_VARS) LOCAL_MODULE_TAGS:=optional LOCAL_MODULE:=i2c-util LOCAL_SRC_FILES+=\ i2c-util.c\ include$(BUILD_EXECUTABLE) 编译Android后,上述工具会位于/system/bin目录。在电路板上使用它: [plain] view plain copy /#i2c-rw/dev/i2c-20x380x10 readsalve:38reg:01value:12 /# /#i2c-rw/dev/i2c-20x380x20 readsalve:38reg:02value:81 本文转自 21cnbao 51CTO博客,原文链接:http://blog.51cto.com/21cnbao/976137 ,如需转载请自行联系原作者