1187712Sraj/*- 2187712Sraj * Copyright (C) 2008-2009 Semihalf, Michal Hajduk and Bartlomiej Sieka 3187712Sraj * All rights reserved. 4187712Sraj * 5187712Sraj * Redistribution and use in source and binary forms, with or without 6187712Sraj * modification, are permitted provided that the following conditions 7187712Sraj * are met: 8187712Sraj * 1. Redistributions of source code must retain the above copyright 9187712Sraj * notice, this list of conditions and the following disclaimer. 10187712Sraj * 2. Redistributions in binary form must reproduce the above copyright 11187712Sraj * notice, this list of conditions and the following disclaimer in the 12187712Sraj * documentation and/or other materials provided with the distribution. 13187712Sraj * 14187712Sraj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15187712Sraj * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16187712Sraj * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17187712Sraj * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 18187712Sraj * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19187712Sraj * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20187712Sraj * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21187712Sraj * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22187712Sraj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23187712Sraj * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24187712Sraj * SUCH DAMAGE. 25187712Sraj */ 26187712Sraj 27187712Sraj#include <sys/cdefs.h> 28187712Sraj__FBSDID("$FreeBSD$"); 29187712Sraj 30187712Sraj#include <err.h> 31187712Sraj#include <errno.h> 32187712Sraj#include <sysexits.h> 33187712Sraj#include <fcntl.h> 34187712Sraj#include <stdio.h> 35187712Sraj#include <stdlib.h> 36187712Sraj#include <string.h> 37187712Sraj#include <stdarg.h> 38187712Sraj#include <unistd.h> 39187712Sraj#include <sys/ioctl.h> 40187712Sraj 41187712Sraj#include <dev/iicbus/iic.h> 42187712Sraj 43187712Sraj#define I2C_DEV "/dev/iic0" 44187712Sraj#define I2C_MODE_NOTSET 0 45187712Sraj#define I2C_MODE_NONE 1 46187712Sraj#define I2C_MODE_STOP_START 2 47187712Sraj#define I2C_MODE_REPEATED_START 3 48187712Sraj 49187712Srajstruct options { 50187712Sraj int width; 51187712Sraj int count; 52187712Sraj int verbose; 53187712Sraj int addr_set; 54187712Sraj int binary; 55187712Sraj int scan; 56187712Sraj int skip; 57187712Sraj int reset; 58187712Sraj int mode; 59187712Sraj char dir; 60187712Sraj uint32_t addr; 61187712Sraj uint32_t off; 62187712Sraj}; 63187712Sraj 64187712Srajstruct skip_range { 65187712Sraj int start; 66187712Sraj int end; 67187712Sraj}; 68187712Sraj 69187712Sraj__dead2 static void 70187712Srajusage(void) 71187712Sraj{ 72187712Sraj 73187712Sraj fprintf(stderr, "usage: %s -a addr [-f device] [-d [r|w]] [-o offset] " 74187712Sraj "[-w [0|8|16]] [-c count] [-m [ss|rs|no]] [-b] [-v]\n", 75187712Sraj getprogname()); 76187712Sraj fprintf(stderr, " %s -s [-f device] [-n skip_addr] -v\n", 77187712Sraj getprogname()); 78187712Sraj fprintf(stderr, " %s -r [-f device] -v\n", getprogname()); 79187712Sraj exit(EX_USAGE); 80187712Sraj} 81187712Sraj 82187712Srajstatic struct skip_range 83187712Srajskip_get_range(char *skip_addr) 84187712Sraj{ 85187712Sraj struct skip_range addr_range; 86187712Sraj char *token; 87187712Sraj 88187712Sraj addr_range.start = 0; 89187712Sraj addr_range.end = 0; 90187712Sraj 91187712Sraj token = strsep(&skip_addr, ".."); 92187712Sraj if (token) { 93187712Sraj addr_range.start = strtoul(token, 0, 16); 94187712Sraj token = strsep(&skip_addr, ".."); 95187712Sraj if ((token != NULL) && !atoi(token)) { 96187712Sraj token = strsep(&skip_addr, ".."); 97187712Sraj if (token) 98187712Sraj addr_range.end = strtoul(token, 0, 16); 99187712Sraj } 100187712Sraj } 101187712Sraj 102187712Sraj return (addr_range); 103187712Sraj} 104187712Sraj 105187712Sraj/* Parse the string to get hex 7 bits addresses */ 106187712Srajstatic int 107187712Srajskip_get_tokens(char *skip_addr, int *sk_addr, int max_index) 108187712Sraj{ 109187712Sraj char *token; 110187712Sraj int i; 111187712Sraj 112187712Sraj for (i = 0; i < max_index; i++) { 113187712Sraj token = strsep(&skip_addr, ":"); 114187712Sraj if (token == NULL) 115187712Sraj break; 116187712Sraj sk_addr[i] = strtoul(token, 0, 16); 117187712Sraj } 118187712Sraj return (i); 119187712Sraj} 120187712Sraj 121187712Srajstatic int 122187712Srajscan_bus(struct iiccmd cmd, char *dev, int skip, char *skip_addr) 123187712Sraj{ 124187712Sraj struct skip_range addr_range = { 0, 0 }; 125187712Sraj int *tokens, fd, error, i, index, j; 126187712Sraj int len = 0, do_skip = 0, no_range = 1; 127187712Sraj 128187712Sraj fd = open(dev, O_RDWR); 129187712Sraj if (fd == -1) { 130187712Sraj fprintf(stderr, "Error opening I2C controller (%s) for " 131187712Sraj "scanning: %s\n", dev, strerror(errno)); 132187712Sraj return (EX_NOINPUT); 133187712Sraj } 134187712Sraj 135187712Sraj if (skip) { 136187712Sraj len = strlen(skip_addr); 137187712Sraj if (strstr(skip_addr, "..") != NULL) { 138187712Sraj addr_range = skip_get_range(skip_addr); 139187712Sraj no_range = 0; 140187712Sraj } else { 141187712Sraj tokens = (int *)malloc((len / 2 + 1) * sizeof(int)); 142187712Sraj if (tokens == NULL) { 143187712Sraj fprintf(stderr, "Error allocating tokens " 144187712Sraj "buffer\n"); 145187712Sraj goto out; 146187712Sraj } 147187712Sraj index = skip_get_tokens(skip_addr, tokens, 148187712Sraj len / 2 + 1); 149187712Sraj } 150187712Sraj 151187712Sraj if (!no_range && (addr_range.start > addr_range.end)) { 152187712Sraj fprintf(stderr, "Skip address out of range\n"); 153187712Sraj goto out; 154187712Sraj } 155187712Sraj } 156187712Sraj 157187712Sraj printf("Scanning I2C devices on %s: ", dev); 158187712Sraj for (i = 1; i < 127; i++) { 159187712Sraj 160187712Sraj if (skip && ( addr_range.start < addr_range.end)) { 161187712Sraj if (i >= addr_range.start && i <= addr_range.end) 162187712Sraj continue; 163187712Sraj 164187712Sraj } else if (skip && no_range) 165187712Sraj for (j = 0; j < index; j++) { 166187712Sraj if (tokens[j] == i) { 167187712Sraj do_skip = 1; 168187712Sraj break; 169187712Sraj } 170187712Sraj } 171187712Sraj 172187712Sraj if (do_skip) { 173187712Sraj do_skip = 0; 174187712Sraj continue; 175187712Sraj } 176187712Sraj 177187712Sraj cmd.slave = i << 1; 178187712Sraj cmd.last = 1; 179187712Sraj cmd.count = 0; 180187712Sraj error = ioctl(fd, I2CRSTCARD, &cmd); 181187712Sraj if (error) 182187712Sraj goto out; 183187712Sraj 184187712Sraj cmd.slave = i << 1; 185187712Sraj cmd.last = 1; 186187712Sraj error = ioctl(fd, I2CSTART, &cmd); 187187712Sraj if (!error) 188187712Sraj printf("%x ", i); 189187712Sraj cmd.slave = i << 1; 190187712Sraj cmd.last = 1; 191187712Sraj error = ioctl(fd, I2CSTOP, &cmd); 192187712Sraj } 193187712Sraj printf("\n"); 194187712Sraj 195187712Sraj error = ioctl(fd, I2CRSTCARD, &cmd); 196187712Srajout: 197187712Sraj close(fd); 198187712Sraj if (skip && no_range) 199187712Sraj free(tokens); 200187712Sraj 201187712Sraj if (error) { 202187712Sraj fprintf(stderr, "Error scanning I2C controller (%s): %s\n", 203187712Sraj dev, strerror(errno)); 204187712Sraj return (EX_NOINPUT); 205187712Sraj } else 206187712Sraj return (EX_OK); 207187712Sraj} 208187712Sraj 209187712Srajstatic int 210187712Srajreset_bus(struct iiccmd cmd, char *dev) 211187712Sraj{ 212187712Sraj int fd, error; 213187712Sraj 214187712Sraj fd = open(dev, O_RDWR); 215187712Sraj if (fd == -1) { 216187712Sraj fprintf(stderr, "Error opening I2C controller (%s) for " 217187712Sraj "resetting: %s\n", dev, strerror(errno)); 218187712Sraj return (EX_NOINPUT); 219187712Sraj } 220187712Sraj 221187712Sraj printf("Resetting I2C controller on %s: ", dev); 222187712Sraj error = ioctl(fd, I2CRSTCARD, &cmd); 223187712Sraj close (fd); 224187712Sraj 225187712Sraj if (error) { 226187712Sraj printf("error: %s\n", strerror(errno)); 227187712Sraj return (EX_IOERR); 228187712Sraj } else { 229187712Sraj printf("OK\n"); 230187712Sraj return (EX_OK); 231187712Sraj } 232187712Sraj} 233187712Sraj 234187712Srajstatic char * 235187712Srajprepare_buf(int size, uint32_t off) 236187712Sraj{ 237187712Sraj char *buf; 238187712Sraj 239187712Sraj buf = malloc(size); 240187712Sraj if (buf == NULL) 241187712Sraj return (buf); 242187712Sraj 243187712Sraj if (size == 1) 244187712Sraj buf[0] = off & 0xff; 245187712Sraj else if (size == 2) { 246187712Sraj buf[0] = (off >> 8) & 0xff; 247187712Sraj buf[1] = off & 0xff; 248187712Sraj } 249187712Sraj 250187712Sraj return (buf); 251187712Sraj} 252187712Sraj 253187712Srajstatic int 254187712Sraji2c_write(char *dev, struct options i2c_opt, char *i2c_buf) 255187712Sraj{ 256187712Sraj struct iiccmd cmd; 257187712Sraj int ch, i, error, fd, bufsize; 258187712Sraj char *err_msg, *buf; 259187712Sraj 260187712Sraj /* 261187712Sraj * Read data to be written to the chip from stdin 262187712Sraj */ 263187712Sraj if (i2c_opt.verbose && !i2c_opt.binary) 264187712Sraj fprintf(stderr, "Enter %u bytes of data: ", i2c_opt.count); 265187712Sraj 266187712Sraj for (i = 0; i < i2c_opt.count; i++) { 267187712Sraj ch = getchar(); 268187712Sraj if (ch == EOF) { 269187712Sraj free(i2c_buf); 270187712Sraj err(1, "not enough data, exiting\n"); 271187712Sraj } 272187712Sraj i2c_buf[i] = ch; 273187712Sraj } 274187712Sraj 275187712Sraj fd = open(dev, O_RDWR); 276187712Sraj if (fd == -1) { 277187712Sraj free(i2c_buf); 278187712Sraj err(1, "open failed"); 279187712Sraj } 280187712Sraj 281187712Sraj /* 282187712Sraj * Write offset where the data will go 283187712Sraj */ 284187712Sraj cmd.slave = i2c_opt.addr; 285187712Sraj error = ioctl(fd, I2CSTART, &cmd); 286187712Sraj if (error == -1) { 287187712Sraj err_msg = "ioctl: error sending start condition"; 288187712Sraj goto err1; 289187712Sraj } 290187712Sraj 291187712Sraj if (i2c_opt.width) { 292187712Sraj bufsize = i2c_opt.width / 8; 293187712Sraj buf = prepare_buf(bufsize, i2c_opt.off); 294187712Sraj if (buf == NULL) { 295187712Sraj err_msg = "error: offset malloc"; 296187712Sraj goto err1; 297187712Sraj } 298187712Sraj 299187712Sraj cmd.count = bufsize; 300187712Sraj cmd.buf = buf; 301187712Sraj error = ioctl(fd, I2CWRITE, &cmd); 302187712Sraj free(buf); 303187712Sraj if (error == -1) { 304187712Sraj err_msg = "ioctl: error when write offset"; 305187712Sraj goto err1; 306187712Sraj } 307187712Sraj } 308187712Sraj 309187712Sraj /* Mode - stop start */ 310187712Sraj if (i2c_opt.mode == I2C_MODE_STOP_START) { 311187712Sraj cmd.slave = i2c_opt.addr; 312187712Sraj error = ioctl(fd, I2CSTOP, &cmd); 313187712Sraj if (error == -1) { 314187712Sraj err_msg = "ioctl: error sending stop condition"; 315187712Sraj goto err2; 316187712Sraj } 317187712Sraj cmd.slave = i2c_opt.addr; 318187712Sraj error = ioctl(fd, I2CSTART, &cmd); 319187712Sraj if (error == -1) { 320187712Sraj err_msg = "ioctl: error sending start condition"; 321187712Sraj goto err1; 322187712Sraj } 323187712Sraj } 324187712Sraj /* Mode - repeated start */ 325187712Sraj if (i2c_opt.mode == I2C_MODE_REPEATED_START) { 326187712Sraj cmd.slave = i2c_opt.addr; 327187712Sraj error = ioctl(fd, I2CRPTSTART, &cmd); 328187712Sraj if (error == -1) { 329187712Sraj err_msg = "ioctl: error sending repeated start " 330187712Sraj "condition"; 331187712Sraj goto err1; 332187712Sraj } 333187712Sraj } 334187712Sraj 335187712Sraj /* 336187712Sraj * Write the data 337187712Sraj */ 338187712Sraj cmd.count = i2c_opt.count; 339187712Sraj cmd.buf = i2c_buf; 340187712Sraj cmd.last = 0; 341187712Sraj error = ioctl(fd, I2CWRITE, &cmd); 342187712Sraj if (error == -1) { 343187712Sraj err_msg = "ioctl: error when write"; 344187712Sraj goto err1; 345187712Sraj } 346187712Sraj cmd.slave = i2c_opt.addr; 347187712Sraj error = ioctl(fd, I2CSTOP, &cmd); 348187712Sraj if (error == -1) { 349187712Sraj err_msg = "ioctl: error sending stop condition"; 350187712Sraj goto err2; 351187712Sraj } 352187712Sraj 353187712Sraj close(fd); 354187712Sraj return (0); 355187712Sraj 356187712Srajerr1: 357187712Sraj cmd.slave = i2c_opt.addr; 358187712Sraj error = ioctl(fd, I2CSTOP, &cmd); 359187712Sraj if (error == -1) 360187712Sraj fprintf(stderr, "error sending stop condtion\n"); 361187712Srajerr2: 362187712Sraj if (err_msg) 363229217Sdim fprintf(stderr, "%s", err_msg); 364187712Sraj 365187712Sraj close(fd); 366187712Sraj return (1); 367187712Sraj} 368187712Sraj 369187712Srajstatic int 370187712Sraji2c_read(char *dev, struct options i2c_opt, char *i2c_buf) 371187712Sraj{ 372187712Sraj struct iiccmd cmd; 373187712Sraj int i, fd, error, bufsize; 374187712Sraj char *err_msg, data = 0, *buf; 375187712Sraj 376187712Sraj fd = open(dev, O_RDWR); 377187712Sraj if (fd == -1) 378187712Sraj err(1, "open failed"); 379187712Sraj 380187712Sraj bzero(&cmd, sizeof(cmd)); 381187712Sraj 382187712Sraj if (i2c_opt.width) { 383187712Sraj cmd.slave = i2c_opt.addr; 384187712Sraj cmd.count = 1; 385187712Sraj cmd.last = 0; 386187712Sraj cmd.buf = &data; 387187712Sraj error = ioctl(fd, I2CSTART, &cmd); 388187712Sraj if (error == -1) { 389187712Sraj err_msg = "ioctl: error sending start condition"; 390187712Sraj goto err1; 391187712Sraj } 392187712Sraj bufsize = i2c_opt.width / 8; 393187712Sraj buf = prepare_buf(bufsize, i2c_opt.off); 394187712Sraj if (buf == NULL) { 395187712Sraj err_msg = "error: offset malloc"; 396187712Sraj goto err1; 397187712Sraj } 398187712Sraj 399187712Sraj cmd.count = bufsize; 400187712Sraj cmd.buf = buf; 401187712Sraj cmd.last = 0; 402187712Sraj error = ioctl(fd, I2CWRITE, &cmd); 403187712Sraj free(buf); 404187712Sraj if (error == -1) { 405187712Sraj err_msg = "ioctl: error when write offset"; 406187712Sraj goto err1; 407187712Sraj } 408187712Sraj 409187712Sraj if (i2c_opt.mode == I2C_MODE_STOP_START) { 410187712Sraj cmd.slave = i2c_opt.addr; 411187712Sraj error = ioctl(fd, I2CSTOP, &cmd); 412187712Sraj if (error == -1) 413187712Sraj goto err2; 414187712Sraj } 415187712Sraj } 416187712Sraj cmd.slave = i2c_opt.addr; 417187712Sraj cmd.count = 1; 418187712Sraj cmd.last = 0; 419187712Sraj cmd.buf = &data; 420187712Sraj if (i2c_opt.mode == I2C_MODE_STOP_START) { 421187712Sraj error = ioctl(fd, I2CSTART, &cmd); 422187712Sraj if (error == -1) { 423187712Sraj err_msg = "ioctl: error sending start condition"; 424187712Sraj goto err1; 425187712Sraj } 426187712Sraj } else if (i2c_opt.mode == I2C_MODE_REPEATED_START) { 427187712Sraj error = ioctl(fd, I2CRPTSTART, &cmd); 428187712Sraj if (error == -1) { 429187712Sraj err_msg = "ioctl: error sending repeated start " 430187712Sraj "condition"; 431187712Sraj goto err1; 432187712Sraj } 433187712Sraj } 434187712Sraj error = ioctl(fd, I2CSTOP, &cmd); 435187712Sraj if (error == -1) 436187712Sraj goto err2; 437187712Sraj 438187712Sraj for (i = 0; i < i2c_opt.count; i++) { 439187712Sraj error = read(fd, &i2c_buf[i], 1); 440187712Sraj if (error == -1) { 441187712Sraj err_msg = "ioctl: error while reading"; 442187712Sraj goto err1; 443187712Sraj } 444187712Sraj } 445187712Sraj 446187712Sraj close(fd); 447187712Sraj return (0); 448187712Sraj 449187712Srajerr1: 450187712Sraj cmd.slave = i2c_opt.addr; 451187712Sraj error = ioctl(fd, I2CSTOP, &cmd); 452187712Sraj if (error == -1) 453187712Sraj fprintf(stderr, "error sending stop condtion\n"); 454187712Srajerr2: 455187712Sraj if (err_msg) 456229217Sdim fprintf(stderr, "%s", err_msg); 457187712Sraj 458187712Sraj close(fd); 459187712Sraj return (1); 460187712Sraj} 461187712Sraj 462187712Srajint 463187712Srajmain(int argc, char** argv) 464187712Sraj{ 465187712Sraj struct iiccmd cmd; 466187712Sraj struct options i2c_opt; 467187712Sraj char *dev, *skip_addr, *err_msg, *i2c_buf; 468187712Sraj int error, chunk_size, i, j, ch; 469187712Sraj 470187712Sraj errno = 0; 471187712Sraj error = 0; 472187712Sraj 473187712Sraj /* Line-break the output every chunk_size bytes */ 474187712Sraj chunk_size = 16; 475187712Sraj 476187712Sraj dev = I2C_DEV; 477187712Sraj err_msg = NULL; 478187712Sraj 479187712Sraj /* Default values */ 480187712Sraj i2c_opt.addr_set = 0; 481187712Sraj i2c_opt.off = 0; 482187712Sraj i2c_opt.verbose = 0; 483187712Sraj i2c_opt.dir = 'r'; /* direction = read */ 484187712Sraj i2c_opt.width = 8; 485187712Sraj i2c_opt.count = 1; 486187712Sraj i2c_opt.binary = 0; /* ASCII text output */ 487187712Sraj i2c_opt.scan = 0; /* no bus scan */ 488187712Sraj i2c_opt.skip = 0; /* scan all addresses */ 489187712Sraj i2c_opt.reset = 0; /* no bus reset */ 490187712Sraj i2c_opt.mode = I2C_MODE_NOTSET; 491187712Sraj 492187712Sraj while ((ch = getopt(argc, argv, "a:f:d:o:w:c:m:n:sbvrh")) != -1) { 493187712Sraj switch(ch) { 494187712Sraj case 'a': 495187712Sraj i2c_opt.addr = (strtoul(optarg, 0, 16) << 1); 496187712Sraj if (i2c_opt.addr == 0 && errno == EINVAL) 497187712Sraj i2c_opt.addr_set = 0; 498187712Sraj else 499187712Sraj i2c_opt.addr_set = 1; 500187712Sraj break; 501187712Sraj case 'f': 502187712Sraj dev = optarg; 503187712Sraj break; 504187712Sraj case 'd': 505187712Sraj i2c_opt.dir = optarg[0]; 506187712Sraj break; 507187712Sraj case 'o': 508187712Sraj i2c_opt.off = strtoul(optarg, 0, 16); 509187712Sraj if (i2c_opt.off == 0 && errno == EINVAL) 510187712Sraj error = 1; 511187712Sraj break; 512187712Sraj case 'w': 513187712Sraj i2c_opt.width = atoi(optarg); 514187712Sraj break; 515187712Sraj case 'c': 516187712Sraj i2c_opt.count = atoi(optarg); 517187712Sraj break; 518187712Sraj case 'm': 519187712Sraj if (!strcmp(optarg, "no")) 520187712Sraj i2c_opt.mode = I2C_MODE_NONE; 521187712Sraj else if (!strcmp(optarg, "ss")) 522187712Sraj i2c_opt.mode = I2C_MODE_STOP_START; 523187712Sraj else if (!strcmp(optarg, "rs")) 524187712Sraj i2c_opt.mode = I2C_MODE_REPEATED_START; 525187712Sraj else 526187712Sraj usage(); 527187712Sraj break; 528187712Sraj case 'n': 529187712Sraj i2c_opt.skip = 1; 530187712Sraj skip_addr = optarg; 531187712Sraj break; 532187712Sraj case 's': 533187712Sraj i2c_opt.scan = 1; 534187712Sraj break; 535187712Sraj case 'b': 536187712Sraj i2c_opt.binary = 1; 537187712Sraj break; 538187712Sraj case 'v': 539187712Sraj i2c_opt.verbose = 1; 540187712Sraj break; 541187712Sraj case 'r': 542187712Sraj i2c_opt.reset = 1; 543187712Sraj break; 544187712Sraj case 'h': 545187712Sraj default: 546187712Sraj usage(); 547187712Sraj } 548187712Sraj } 549187712Sraj argc -= optind; 550187712Sraj argv += optind; 551187712Sraj 552187712Sraj /* Set default mode if option -m is not specified */ 553187712Sraj if (i2c_opt.mode == I2C_MODE_NOTSET) { 554187712Sraj if (i2c_opt.dir == 'r') 555187712Sraj i2c_opt.mode = I2C_MODE_STOP_START; 556187712Sraj else if (i2c_opt.dir == 'w') 557187712Sraj i2c_opt.mode = I2C_MODE_NONE; 558187712Sraj } 559187712Sraj 560187712Sraj /* Basic sanity check of command line arguments */ 561187712Sraj if (i2c_opt.scan) { 562187712Sraj if (i2c_opt.addr_set) 563187712Sraj usage(); 564187712Sraj } else if (i2c_opt.reset) { 565187712Sraj if (i2c_opt.addr_set) 566187712Sraj usage(); 567187712Sraj } else if (error) { 568187712Sraj usage(); 569187712Sraj } else if ((i2c_opt.dir == 'r' || i2c_opt.dir == 'w')) { 570187712Sraj if ((i2c_opt.addr_set == 0) || 571187712Sraj !(i2c_opt.width == 0 || i2c_opt.width == 8 || 572187712Sraj i2c_opt.width == 16)) 573187712Sraj usage(); 574187712Sraj } 575187712Sraj 576187712Sraj if (i2c_opt.verbose) 577187712Sraj fprintf(stderr, "dev: %s, addr: 0x%x, r/w: %c, " 578187712Sraj "offset: 0x%02x, width: %u, count: %u\n", dev, 579187712Sraj i2c_opt.addr >> 1, i2c_opt.dir, i2c_opt.off, 580187712Sraj i2c_opt.width, i2c_opt.count); 581187712Sraj 582187712Sraj if (i2c_opt.scan) 583187712Sraj exit(scan_bus(cmd, dev, i2c_opt.skip, skip_addr)); 584187712Sraj 585187712Sraj if (i2c_opt.reset) 586187712Sraj exit(reset_bus(cmd, dev)); 587187712Sraj 588187712Sraj i2c_buf = malloc(i2c_opt.count); 589187712Sraj if (i2c_buf == NULL) 590187712Sraj err(1, "data malloc"); 591187712Sraj 592187712Sraj if (i2c_opt.dir == 'w') { 593187712Sraj error = i2c_write(dev, i2c_opt, i2c_buf); 594187712Sraj if (error) { 595187712Sraj free(i2c_buf); 596187712Sraj return (1); 597187712Sraj } 598187712Sraj } 599187712Sraj if (i2c_opt.dir == 'r') { 600187712Sraj error = i2c_read(dev, i2c_opt, i2c_buf); 601187712Sraj if (error) { 602187712Sraj free(i2c_buf); 603187712Sraj return (1); 604187712Sraj } 605187712Sraj } 606187712Sraj 607187712Sraj if (i2c_opt.verbose) 608187712Sraj fprintf(stderr, "\nData %s (hex):\n", i2c_opt.dir == 'r' ? 609187712Sraj "read" : "written"); 610187712Sraj 611187712Sraj i = 0; 612187712Sraj j = 0; 613187712Sraj while (i < i2c_opt.count) { 614187712Sraj if (i2c_opt.verbose || (i2c_opt.dir == 'r' && 615187712Sraj !i2c_opt.binary)) 616187712Sraj fprintf (stderr, "%02hhx ", i2c_buf[i++]); 617187712Sraj 618187712Sraj if (i2c_opt.dir == 'r' && i2c_opt.binary) { 619187712Sraj fprintf(stdout, "%c", i2c_buf[j++]); 620187712Sraj if(!i2c_opt.verbose) 621187712Sraj i++; 622187712Sraj } 623187712Sraj if (!i2c_opt.verbose && (i2c_opt.dir == 'w')) 624187712Sraj break; 625187712Sraj if ((i % chunk_size) == 0) 626187712Sraj fprintf(stderr, "\n"); 627187712Sraj } 628187712Sraj if ((i % chunk_size) != 0) 629187712Sraj fprintf(stderr, "\n"); 630187712Sraj 631187712Sraj free(i2c_buf); 632187712Sraj return (0); 633187712Sraj} 634