📄 i2c.c
字号:
/* * Sample program for FR400 Companion Chip I2C axLinux driver. * * Copyright (C) 2002 AXE,Inc. * */#include <stdio.h>#include <stdlib.h>#include <time.h>#include <fcntl.h>#include <unistd.h>#include <sys/mman.h>#include <linux/fr400cc_i2c.h>#define CFGCHK 1 /* 2002/Dec/20 */#define OPTCHK 1 /* 2002/Dec/19 */#define SEND_RECV 1#define I2C_REPEAT_START 1#define CH1 1#if CFGCHKstatic int v16 = 0;#elsestatic int verb = 0;#endifstatic voidhelp(){ printf("--help , -help , -?\n"); printf("-colorbar\n"); printf("-nocolorbar\n"); printf("-nonblock N (N=0|1 , default:1\n"); printf("-block ( == -nonblock 0)\n"); printf("-test-req-sbuf\n");#if I2C_REPEAT_START printf("-rd-reg <slave addr> <sub addr>\n"); printf("-wt-reg <slave addr> <sub addr> <value>\n");#endif#if CFGCHK printf("-v16\n"); printf("-v\n");#else printf("-ver, -verbose\n");#endif}static intopt_chk(int ac, char **av, char *key){ int i; for(i=1; i<ac; i++){ if(strcmp(av[i], key) == 0) return i; } return 0;}static voidopt_chk_str(int ac, char **av, char *key, char **re){ int i; i = opt_chk(ac, av, key); if(i!=0 && i+1<ac){ *re = av[i+1]; }}static intint_get(char *s){ int v; if(strncmp(s, "0x", 2) == 0){ sscanf(s, "0x%x", &v); return v; } sscanf(s, "%d", &v); return v;}static voidopt_chk_int(int ac, char **av, char *key, int *re){ int i; i = opt_chk(ac, av, key); if(i!=0 && i+1<ac){ *re = int_get(av[i+1]); }}static voidopt_chk_int2(int ac, char **av, char *key, int *re1, int *re2){ int i; i = opt_chk(ac, av, key); if(i!=0 && i+2<ac){ *re1 = int_get(av[i+1]); *re2 = int_get(av[i+2]); }}static voidopt_chk_int3(int ac, char **av, char *key, int *re1, int *re2, int *re3){ int i; i = opt_chk(ac, av, key); if(i!=0 && i+3<ac){ *re1 = int_get(av[i+1]); *re2 = int_get(av[i+2]); *re3 = int_get(av[i+3]); }}#if CFGCHKstatic int verbose = 0;static voidconfig_show(struct fr400i2c_config *cfg){ printf("addr=%02x mss=%d hsm=%d cs=0x%08x bufsz=%d\n", (unsigned)cfg->addr, cfg->mss, cfg->hsm, (unsigned)cfg->cs, cfg->bufsz);}static intioctl_start(int fd, int start_cmd, void *prm){ if(verbose){ struct fr400i2c_config cfg; if(ioctl(fd, I2CIOCGCFG, &cfg) != 0){ fprintf(stderr, "ioctl get cfg err\n"); return -1; } config_show(&cfg); } return ioctl(fd, start_cmd, prm);}#endif /* CFGCHK */static void *mmap_fd(int fd, int bufsz){ void *start; int length, prot, flags, offset; start = NULL; length = bufsz; prot = PROT_READ | PROT_WRITE; flags = MAP_SHARED; offset = 0; return mmap(start, length, prot, flags, fd, offset);}#if I2C_REPEAT_STARTstatic char *err_msg(int kind){ switch(kind){ case FR400CC_I2C_RCOUNT_ERR_DETECT_BUSERR: return "bus error"; case FR400CC_I2C_RCOUNT_ERR_DETECT_STOP_COND: return "detect stop condition error"; case FR400CC_I2C_RCOUNT_ERR_DETECT_RSTART_COND: return "detect rstart condition error"; case FR400CC_I2C_RCOUNT_ERR_DETECT_ARBITO_LOST: return "detect arbito lost error"; case FR400CC_I2C_RCOUNT_ERR_DETECT_NACK: return "detect nack error"; } return "???";}static intrd_work(int fd, int nonblock, struct fr400i2c_read *rinf){ fd_set setr; int run, ret; int i, n, x; run = 1; while(run){ if(nonblock){ FD_ZERO(&setr); FD_SET(fd, &setr); x = select(fd+1, &setr, NULL, NULL, NULL); if(x <= 0 || !FD_ISSET(fd, &setr)) continue; } if(read(fd, (void*)rinf, sizeof(*rinf)) <= 0) continue; run = 0; } return 0;}#if 1 /* test */static intrd_reg_work3( int fd, int nonblock, int slave_addr, int subaddr, struct fr400i2c_config *cfg, char *buf){ struct fr400i2c_master mst; struct fr400i2c_sbuf sbuf; struct fr400i2c_read rinf; int i; bzero(&mst, sizeof(mst)); mst.addr = slave_addr; mst.bytes = 16; sbuf.offset = 0; sbuf.bytes = 16; if(ioctl(fd, I2CIOCSBUF, &sbuf) != 0){ fprintf(stderr, "err ioctl sbuf\n"); goto err; }#if CFGCHK if(ioctl_start(fd, I2CIOCRECV, &mst) != 0){#else if(ioctl(fd, I2CIOCRECV, &mst) != 0){#endif fprintf(stderr, "err ioctl send\n"); goto err; } if(rd_work(fd, nonblock, &rinf) != 0){ fprintf(stderr, "err rd_work\n"); goto err; } switch(rinf.type){ case FR400CC_I2C_RTYPE_TRANS_FIN: break; case FR400CC_I2C_RTYPE_REQ_SBUF: fprintf(stderr, "req_sbuf ??\n"); goto err; case FR400CC_I2C_RTYPE_ERR: fprintf(stderr, "err <0x%x> %s\n", rinf.count, err_msg(rinf.count)); goto err; } for(i=0; i<sbuf.bytes; i++){ printf("%02x ", ((unsigned char *)buf)[sbuf.offset+i]); } printf("\n"); close(fd); return 0;err: close(fd); return -1;}#endif#if SEND_RECVstatic intrd_reg_work_send_recv( int fd, int nonblock, int slave_addr, int subaddr, struct fr400i2c_config *cfg, char *buf){ struct fr400i2c_send_recv prm; struct fr400i2c_master mst; struct fr400i2c_sbuf sbuf; struct fr400i2c_read rinf; int i; bzero(&prm, sizeof(prm)); prm.mst_send.addr = slave_addr; buf[0] = subaddr; prm.mst_send.bytes = 1; prm.sbuf_send.offset = 0; prm.sbuf_send.bytes = prm.mst_send.bytes; prm.mst_recv.addr = slave_addr; prm.mst_recv.bytes = 1;#if CFGCHK if(v16){#else if(verb){#endif prm.mst_recv.bytes = 16; } prm.sbuf_recv.offset = 1; prm.sbuf_recv.bytes = prm.mst_recv.bytes;#if CFGCHK if(ioctl_start(fd, I2CIOCSEND_RECV, &prm) != 0){#else if(ioctl(fd, I2CIOCSEND_RECV, &prm) != 0){#endif fprintf(stderr, "err ioctl send_recv\n"); goto err; } if(rd_work(fd, nonblock, &rinf) != 0){ fprintf(stderr, "err rd_work\n"); goto err; } switch(rinf.type){ case FR400CC_I2C_RTYPE_TRANS_FIN: break; case FR400CC_I2C_RTYPE_REQ_SBUF: fprintf(stderr, "req_sbuf ??\n"); goto err; case FR400CC_I2C_RTYPE_ERR: fprintf(stderr, "err <0x%x> %s\n", rinf.count, err_msg(rinf.count)); goto err; } printf("slave_addr 0x%02x , subaddr 0x%02x value ", slave_addr, subaddr); for(i=0; i<prm.sbuf_recv.bytes; i++){ printf("%02x ", ((unsigned char *)buf)[prm.sbuf_recv.offset+i]); } printf("\n"); close(fd); return 0;err: close(fd); return -1;}#endif#if SEND_RECV/* cut */#elsestatic intrd_reg_work( int fd, int nonblock, int slave_addr, int subaddr, struct fr400i2c_config *cfg, char *buf){ struct fr400i2c_master mst; struct fr400i2c_sbuf sbuf; struct fr400i2c_read rinf; int i; bzero(&mst, sizeof(mst)); mst.addr = slave_addr; buf[0] = subaddr; mst.bytes = 1; mst.no_stop_cond = 1; mst.repeat_start = 0; sbuf.offset = 0; sbuf.bytes = 1; if(ioctl(fd, I2CIOCSBUF, &sbuf) != 0){ fprintf(stderr, "err ioctl sbuf\n"); goto err; }#if CFGCHK if(ioctl_start(fd, I2CIOCSEND, &mst) != 0){#else if(ioctl(fd, I2CIOCSEND, &mst) != 0){#endif fprintf(stderr, "err ioctl send\n"); goto err; } if(rd_work(fd, nonblock, &rinf) != 0){ fprintf(stderr, "err rd_work\n"); goto err; } switch(rinf.type){ case FR400CC_I2C_RTYPE_TRANS_FIN: break; case FR400CC_I2C_RTYPE_REQ_SBUF: fprintf(stderr, "req_sbuf ??\n"); goto err; case FR400CC_I2C_RTYPE_ERR: fprintf(stderr, "err <0x%x> %s\n", rinf.count, err_msg(rinf.count)); goto err; } /**/ mst.bytes = 1; mst.no_stop_cond = 0; mst.repeat_start = 1; sbuf.offset = 1; sbuf.bytes = mst.bytes; if(ioctl(fd, I2CIOCSBUF, &sbuf) != 0){ fprintf(stderr, "err ioctl sbuf\n"); goto err; }#if CFGCHK if(ioctl_start(fd, I2CIOCRECV, &mst) != 0){#else if(ioctl(fd, I2CIOCRECV, &mst) != 0){#endif fprintf(stderr, "err ioctl send\n"); goto err; } if(rd_work(fd, nonblock, &rinf) != 0){ fprintf(stderr, "err rd_work\n"); goto err; } switch(rinf.type){ case FR400CC_I2C_RTYPE_TRANS_FIN: break; case FR400CC_I2C_RTYPE_REQ_SBUF: fprintf(stderr, "req_sbuf ??\n"); goto err; case FR400CC_I2C_RTYPE_ERR: fprintf(stderr, "err <0x%x> %s\n", rinf.count, err_msg(rinf.count)); goto err; } printf("slave_addr 0x%02x , subaddr 0x%02x value 0x%02x\n", slave_addr, subaddr, ((unsigned char *)buf)[1]); close(fd); return 0;err: close(fd); return -1;}#endifstatic intwt_reg_work( int fd, int nonblock, int slave_addr, int subaddr, int value, struct fr400i2c_config *cfg, char *buf){ struct fr400i2c_master mst; struct fr400i2c_sbuf sbuf; struct fr400i2c_read rinf; bzero(&mst, sizeof(mst)); mst.addr = slave_addr; buf[0] = subaddr; buf[1] = value; mst.bytes = 2; sbuf.offset = 0; sbuf.bytes = 2; if(ioctl(fd, I2CIOCSBUF, &sbuf) != 0){ fprintf(stderr, "err ioctl sbuf\n"); goto err; }#if CFGCHK if(ioctl_start(fd, I2CIOCSEND, &mst) != 0){#else if(ioctl(fd, I2CIOCSEND, &mst) != 0){#endif fprintf(stderr, "err ioctl send\n"); goto err; } if(rd_work(fd, nonblock, &rinf) != 0){ fprintf(stderr, "err rd_work\n"); goto err; } switch(rinf.type){ case FR400CC_I2C_RTYPE_TRANS_FIN: break; case FR400CC_I2C_RTYPE_REQ_SBUF: fprintf(stderr, "req_sbuf ??\n"); goto err; case FR400CC_I2C_RTYPE_ERR: fprintf(stderr, "err <0x%x> %s\n", rinf.count, err_msg(rinf.count)); goto err; } close(fd); printf("(^_^)/~~~\n"); return 0;err: close(fd); return -1;}#endif /* I2C_REPEAT_START */#if OPTCHKstatic char *opt_list[] = {"-help", "help", "?",#if CFGCHK"v16", "v",#else"ver", "verbose",#endif"colorbar","nocolorbar","test-req-sbuf","nonblock", "block","rd-reg", "wt-reg","type3", "ch1",};static intoptchk_top(int ac, char **av){ int i, j, n, ret; ret = 0; n = sizeof(opt_list) / sizeof(opt_list[0]); for(i=1; i<ac; i++){ if(av[i][0] != '-') continue; if('0' <= av[i][1] && av[i][1] <= '9') continue; for(j=0; j<n; j++){ if(strcmp(&av[i][1], opt_list[j]) == 0) break; } if(j<n) continue; fprintf(stderr, "ignore option '%s' ?\n", av[i]); ret = -1; } return ret;}#endif /* OPTCHK */main(int ac, char **av){ int nonblock, colorbar; int fd, open_flag; struct fr400i2c_config cfg; char *buf; int subaddr, run, x, n, i; struct fr400i2c_read rinf[100];#if CH1 char dev_name[32];#endif#if I2C_REPEAT_START int rd_reg, wt_reg, slave_addr, value;#else struct fr400i2c_master mst; struct fr400i2c_sbuf sbuf; fd_set setr; int test_req_sbuf;#endif#if OPTCHK if(optchk_top(ac,av) != 0) return -1;#endif#if CFGCHK verbose = (opt_chk(ac,av, "-v") != 0);#endif if(opt_chk(ac,av,"--help") != 0 || opt_chk(ac,av,"-help") != 0 || opt_chk(ac,av,"-?") != 0){ help(); return 0; }#if CFGCHK v16 = (opt_chk(ac,av,"-v16") != 0);#else verb = opt_chk(ac,av,"-ver") | opt_chk(ac,av,"-verbose");#endif colorbar = opt_chk(ac, av, "-colorbar"); if(opt_chk(ac, av, "-nocolorbar")) colorbar = 0;#if I2C_REPEAT_START#else test_req_sbuf = opt_chk(ac, av, "-test-req-sbuf");#endif nonblock = 1; opt_chk_int(ac, av, "-nonblock", &nonblock); if(nonblock == 1 && opt_chk(ac, av, "-block") != 0){ nonblock = 0; }#if I2C_REPEAT_START rd_reg = 0; slave_addr = -1; opt_chk_int2(ac, av, "-rd-reg", &slave_addr, &subaddr); if(slave_addr != -1){ rd_reg = 1; if(opt_chk(ac, av, "-type3")) rd_reg = 3; }else{ wt_reg = 0; opt_chk_int3(ac, av, "-wt-reg", &slave_addr, &subaddr, &value); if(slave_addr != -1){ wt_reg = 1; rd_reg = 0; } }#endif /* I2C_REPEAT_START */ /**/ open_flag = O_RDONLY; if(nonblock) open_flag |= O_NONBLOCK;#if CH1 sprintf(dev_name, "/dev/fr400cc_i2c%d", opt_chk(ac,av,"-ch1") ? 1 : 0); if((fd = open(dev_name, open_flag)) < 0){#else if((fd = open("/dev/fr400cc_i2c0", open_flag)) < 0){#endif fprintf(stderr, "fd=%d\n", fd); return -1; } if(ioctl(fd, I2CIOCGCFG, &cfg) != 0){ fprintf(stderr, "err ioctl get cfg\n"); close(fd); return -1; } if((buf = mmap_fd(fd, cfg.bufsz)) == (void*)-1){ fprintf(stderr, "err mmap\n"); close(fd); return -1; }#if 0 cfg.addr = cfg.mss = cfg.hsm = cfg.cs = #endif#if CH1 cfg.mss = 1;#endif if(ioctl(fd, I2CIOCSCFG, &cfg) != 0){ fprintf(stderr, "err ioctl set cfg\n"); close(fd); return -1; }#if I2C_REPEAT_START switch(rd_reg){#if SEND_RECV case 1: return rd_reg_work_send_recv(fd, nonblock, #else case 1: return rd_reg_work(fd, nonblock, #endif slave_addr, subaddr, &cfg, buf); case 3: return rd_reg_work3(fd, nonblock, slave_addr, subaddr, &cfg, buf); } if(wt_reg){ return wt_reg_work(fd, nonblock, slave_addr, subaddr, value, &cfg, buf); } return wt_reg_work(fd, nonblock, 0x88, 2, colorbar ? (1<<3) : 0, &cfg, buf);#else /* I2C_REPEAT_START */ /* --> FJDL7654-01 */ mst.addr = 0x88; /* target slave */ subaddr = 2; /* CR0 */ buf[0] = subaddr; buf[1] = 0; if(colorbar){ buf[1] |= (1<<3); /* CR0[3] Color Bar */ } mst.bytes = 2; /* <-- FJDL7654-01 */ sbuf.offset = 0; if(test_req_sbuf){ sbuf.bytes = 1; /* == mst.bytes */ }else{ sbuf.bytes = 2; /* == mst.bytes (all at once) */ } if(ioctl(fd, I2CIOCSBUF, &sbuf) != 0){ fprintf(stderr, "err ioctl sbuf \n"); close(fd); return -1; }#if CFGCHK if(ioctl_start(fd, I2CIOCSEND, &mst) != 0){#else if(ioctl(fd, I2CIOCSEND, &mst) != 0){#endif fprintf(stderr, "err ioctl send \n"); close(fd); return -1; } run = 1; while(run){ if(nonblock){ FD_ZERO(&setr); FD_SET(fd, &setr); x = select(fd+1, &setr, NULL, NULL, NULL); if(x <= 0 || !FD_ISSET(fd, &setr)) continue; } if((x = read(fd, (void*)rinf, sizeof(rinf))) < 0) continue; n = x / sizeof(rinf[0]); for(i=0; i<n; i++){ printf("rinf[%d].type=%d count=%d\n", i, rinf[i].type, rinf[i].count); switch(rinf[i].type){ case FR400CC_I2C_RTYPE_TRANS_FIN: run = 0; break; case FR400CC_I2C_RTYPE_REQ_SBUF: if(test_req_sbuf){ fprintf(stderr, "application get sbuf req\n"); sbuf.offset = 1; sbuf.bytes = 1; if(ioctl(fd, I2CIOCSBUF, &sbuf) != 0){ fprintf(stderr, "err ioctl sbuf 2\n"); close(fd); return -1; } } break; } } } printf("(^_^)/~~~\n"); close(fd); return 0;#endif /* I2C_REPEAT_START */}/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -