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"); 145276876Sloos error = -1; 146187712Sraj goto out; 147187712Sraj } 148187712Sraj index = skip_get_tokens(skip_addr, tokens, 149187712Sraj len / 2 + 1); 150187712Sraj } 151187712Sraj 152187712Sraj if (!no_range && (addr_range.start > addr_range.end)) { 153187712Sraj fprintf(stderr, "Skip address out of range\n"); 154276876Sloos error = -1; 155187712Sraj goto out; 156187712Sraj } 157187712Sraj } 158187712Sraj 159187712Sraj printf("Scanning I2C devices on %s: ", dev); 160187712Sraj for (i = 1; i < 127; i++) { 161187712Sraj 162187712Sraj if (skip && ( addr_range.start < addr_range.end)) { 163187712Sraj if (i >= addr_range.start && i <= addr_range.end) 164187712Sraj continue; 165187712Sraj 166187712Sraj } else if (skip && no_range) 167187712Sraj for (j = 0; j < index; j++) { 168187712Sraj if (tokens[j] == i) { 169187712Sraj do_skip = 1; 170187712Sraj break; 171187712Sraj } 172187712Sraj } 173187712Sraj 174187712Sraj if (do_skip) { 175187712Sraj do_skip = 0; 176187712Sraj continue; 177187712Sraj } 178187712Sraj 179187712Sraj cmd.slave = i << 1; 180187712Sraj cmd.last = 1; 181187712Sraj cmd.count = 0; 182187712Sraj error = ioctl(fd, I2CRSTCARD, &cmd); 183187712Sraj if (error) 184187712Sraj goto out; 185187712Sraj 186187712Sraj cmd.slave = i << 1; 187187712Sraj cmd.last = 1; 188187712Sraj error = ioctl(fd, I2CSTART, &cmd); 189187712Sraj if (!error) 190187712Sraj printf("%x ", i); 191187712Sraj cmd.slave = i << 1; 192187712Sraj cmd.last = 1; 193187712Sraj error = ioctl(fd, I2CSTOP, &cmd); 194187712Sraj } 195187712Sraj printf("\n"); 196187712Sraj 197187712Sraj error = ioctl(fd, I2CRSTCARD, &cmd); 198187712Srajout: 199187712Sraj close(fd); 200187712Sraj if (skip && no_range) 201187712Sraj free(tokens); 202187712Sraj 203187712Sraj if (error) { 204187712Sraj fprintf(stderr, "Error scanning I2C controller (%s): %s\n", 205187712Sraj dev, strerror(errno)); 206187712Sraj return (EX_NOINPUT); 207187712Sraj } else 208187712Sraj return (EX_OK); 209187712Sraj} 210187712Sraj 211187712Srajstatic int 212187712Srajreset_bus(struct iiccmd cmd, char *dev) 213187712Sraj{ 214187712Sraj int fd, error; 215187712Sraj 216187712Sraj fd = open(dev, O_RDWR); 217187712Sraj if (fd == -1) { 218187712Sraj fprintf(stderr, "Error opening I2C controller (%s) for " 219187712Sraj "resetting: %s\n", dev, strerror(errno)); 220187712Sraj return (EX_NOINPUT); 221187712Sraj } 222187712Sraj 223187712Sraj printf("Resetting I2C controller on %s: ", dev); 224187712Sraj error = ioctl(fd, I2CRSTCARD, &cmd); 225187712Sraj close (fd); 226187712Sraj 227187712Sraj if (error) { 228187712Sraj printf("error: %s\n", strerror(errno)); 229187712Sraj return (EX_IOERR); 230187712Sraj } else { 231187712Sraj printf("OK\n"); 232187712Sraj return (EX_OK); 233187712Sraj } 234187712Sraj} 235187712Sraj 236187712Srajstatic char * 237187712Srajprepare_buf(int size, uint32_t off) 238187712Sraj{ 239187712Sraj char *buf; 240187712Sraj 241187712Sraj buf = malloc(size); 242187712Sraj if (buf == NULL) 243187712Sraj return (buf); 244187712Sraj 245187712Sraj if (size == 1) 246187712Sraj buf[0] = off & 0xff; 247187712Sraj else if (size == 2) { 248187712Sraj buf[0] = (off >> 8) & 0xff; 249187712Sraj buf[1] = off & 0xff; 250187712Sraj } 251187712Sraj 252187712Sraj return (buf); 253187712Sraj} 254187712Sraj 255187712Srajstatic int 256187712Sraji2c_write(char *dev, struct options i2c_opt, char *i2c_buf) 257187712Sraj{ 258187712Sraj struct iiccmd cmd; 259187712Sraj int ch, i, error, fd, bufsize; 260187712Sraj char *err_msg, *buf; 261187712Sraj 262187712Sraj /* 263187712Sraj * Read data to be written to the chip from stdin 264187712Sraj */ 265187712Sraj if (i2c_opt.verbose && !i2c_opt.binary) 266187712Sraj fprintf(stderr, "Enter %u bytes of data: ", i2c_opt.count); 267187712Sraj 268187712Sraj for (i = 0; i < i2c_opt.count; i++) { 269187712Sraj ch = getchar(); 270187712Sraj if (ch == EOF) { 271187712Sraj free(i2c_buf); 272187712Sraj err(1, "not enough data, exiting\n"); 273187712Sraj } 274187712Sraj i2c_buf[i] = ch; 275187712Sraj } 276187712Sraj 277187712Sraj fd = open(dev, O_RDWR); 278187712Sraj if (fd == -1) { 279187712Sraj free(i2c_buf); 280187712Sraj err(1, "open failed"); 281187712Sraj } 282187712Sraj 283187712Sraj /* 284187712Sraj * Write offset where the data will go 285187712Sraj */ 286187712Sraj cmd.slave = i2c_opt.addr; 287187712Sraj error = ioctl(fd, I2CSTART, &cmd); 288187712Sraj if (error == -1) { 289187712Sraj err_msg = "ioctl: error sending start condition"; 290187712Sraj goto err1; 291187712Sraj } 292187712Sraj 293187712Sraj if (i2c_opt.width) { 294187712Sraj bufsize = i2c_opt.width / 8; 295187712Sraj buf = prepare_buf(bufsize, i2c_opt.off); 296187712Sraj if (buf == NULL) { 297187712Sraj err_msg = "error: offset malloc"; 298187712Sraj goto err1; 299187712Sraj } 300187712Sraj 301187712Sraj cmd.count = bufsize; 302187712Sraj cmd.buf = buf; 303187712Sraj error = ioctl(fd, I2CWRITE, &cmd); 304187712Sraj free(buf); 305187712Sraj if (error == -1) { 306187712Sraj err_msg = "ioctl: error when write offset"; 307187712Sraj goto err1; 308187712Sraj } 309187712Sraj } 310187712Sraj 311187712Sraj /* Mode - stop start */ 312187712Sraj if (i2c_opt.mode == I2C_MODE_STOP_START) { 313187712Sraj cmd.slave = i2c_opt.addr; 314187712Sraj error = ioctl(fd, I2CSTOP, &cmd); 315187712Sraj if (error == -1) { 316187712Sraj err_msg = "ioctl: error sending stop condition"; 317187712Sraj goto err2; 318187712Sraj } 319187712Sraj cmd.slave = i2c_opt.addr; 320187712Sraj error = ioctl(fd, I2CSTART, &cmd); 321187712Sraj if (error == -1) { 322187712Sraj err_msg = "ioctl: error sending start condition"; 323187712Sraj goto err1; 324187712Sraj } 325187712Sraj } 326187712Sraj /* Mode - repeated start */ 327187712Sraj if (i2c_opt.mode == I2C_MODE_REPEATED_START) { 328187712Sraj cmd.slave = i2c_opt.addr; 329187712Sraj error = ioctl(fd, I2CRPTSTART, &cmd); 330187712Sraj if (error == -1) { 331187712Sraj err_msg = "ioctl: error sending repeated start " 332187712Sraj "condition"; 333187712Sraj goto err1; 334187712Sraj } 335187712Sraj } 336187712Sraj 337187712Sraj /* 338187712Sraj * Write the data 339187712Sraj */ 340187712Sraj cmd.count = i2c_opt.count; 341187712Sraj cmd.buf = i2c_buf; 342187712Sraj cmd.last = 0; 343187712Sraj error = ioctl(fd, I2CWRITE, &cmd); 344187712Sraj if (error == -1) { 345187712Sraj err_msg = "ioctl: error when write"; 346187712Sraj goto err1; 347187712Sraj } 348187712Sraj cmd.slave = i2c_opt.addr; 349187712Sraj error = ioctl(fd, I2CSTOP, &cmd); 350187712Sraj if (error == -1) { 351187712Sraj err_msg = "ioctl: error sending stop condition"; 352187712Sraj goto err2; 353187712Sraj } 354187712Sraj 355187712Sraj close(fd); 356187712Sraj return (0); 357187712Sraj 358187712Srajerr1: 359187712Sraj cmd.slave = i2c_opt.addr; 360187712Sraj error = ioctl(fd, I2CSTOP, &cmd); 361187712Sraj if (error == -1) 362187712Sraj fprintf(stderr, "error sending stop condtion\n"); 363187712Srajerr2: 364187712Sraj if (err_msg) 365228660Sdim fprintf(stderr, "%s", err_msg); 366187712Sraj 367187712Sraj close(fd); 368187712Sraj return (1); 369187712Sraj} 370187712Sraj 371187712Srajstatic int 372187712Sraji2c_read(char *dev, struct options i2c_opt, char *i2c_buf) 373187712Sraj{ 374187712Sraj struct iiccmd cmd; 375187712Sraj int i, fd, error, bufsize; 376187712Sraj char *err_msg, data = 0, *buf; 377187712Sraj 378187712Sraj fd = open(dev, O_RDWR); 379187712Sraj if (fd == -1) 380187712Sraj err(1, "open failed"); 381187712Sraj 382187712Sraj bzero(&cmd, sizeof(cmd)); 383187712Sraj 384187712Sraj if (i2c_opt.width) { 385187712Sraj cmd.slave = i2c_opt.addr; 386187712Sraj cmd.count = 1; 387187712Sraj cmd.last = 0; 388187712Sraj cmd.buf = &data; 389187712Sraj error = ioctl(fd, I2CSTART, &cmd); 390187712Sraj if (error == -1) { 391187712Sraj err_msg = "ioctl: error sending start condition"; 392187712Sraj goto err1; 393187712Sraj } 394187712Sraj bufsize = i2c_opt.width / 8; 395187712Sraj buf = prepare_buf(bufsize, i2c_opt.off); 396187712Sraj if (buf == NULL) { 397187712Sraj err_msg = "error: offset malloc"; 398187712Sraj goto err1; 399187712Sraj } 400187712Sraj 401187712Sraj cmd.count = bufsize; 402187712Sraj cmd.buf = buf; 403187712Sraj cmd.last = 0; 404187712Sraj error = ioctl(fd, I2CWRITE, &cmd); 405187712Sraj free(buf); 406187712Sraj if (error == -1) { 407187712Sraj err_msg = "ioctl: error when write offset"; 408187712Sraj goto err1; 409187712Sraj } 410187712Sraj 411187712Sraj if (i2c_opt.mode == I2C_MODE_STOP_START) { 412187712Sraj cmd.slave = i2c_opt.addr; 413187712Sraj error = ioctl(fd, I2CSTOP, &cmd); 414276876Sloos if (error == -1) { 415276876Sloos err_msg = "error sending stop condtion\n"; 416187712Sraj goto err2; 417276876Sloos } 418187712Sraj } 419187712Sraj } 420187712Sraj cmd.slave = i2c_opt.addr; 421187712Sraj cmd.count = 1; 422187712Sraj cmd.last = 0; 423187712Sraj cmd.buf = &data; 424187712Sraj if (i2c_opt.mode == I2C_MODE_STOP_START) { 425187712Sraj error = ioctl(fd, I2CSTART, &cmd); 426187712Sraj if (error == -1) { 427187712Sraj err_msg = "ioctl: error sending start condition"; 428187712Sraj goto err1; 429187712Sraj } 430187712Sraj } else if (i2c_opt.mode == I2C_MODE_REPEATED_START) { 431187712Sraj error = ioctl(fd, I2CRPTSTART, &cmd); 432187712Sraj if (error == -1) { 433187712Sraj err_msg = "ioctl: error sending repeated start " 434187712Sraj "condition"; 435187712Sraj goto err1; 436187712Sraj } 437187712Sraj } 438187712Sraj error = ioctl(fd, I2CSTOP, &cmd); 439276876Sloos if (error == -1) { 440276876Sloos err_msg = "error sending stop condtion\n"; 441187712Sraj goto err2; 442276876Sloos } 443187712Sraj 444187712Sraj for (i = 0; i < i2c_opt.count; i++) { 445187712Sraj error = read(fd, &i2c_buf[i], 1); 446187712Sraj if (error == -1) { 447187712Sraj err_msg = "ioctl: error while reading"; 448187712Sraj goto err1; 449187712Sraj } 450187712Sraj } 451187712Sraj 452187712Sraj close(fd); 453187712Sraj return (0); 454187712Sraj 455187712Srajerr1: 456187712Sraj cmd.slave = i2c_opt.addr; 457187712Sraj error = ioctl(fd, I2CSTOP, &cmd); 458187712Sraj if (error == -1) 459187712Sraj fprintf(stderr, "error sending stop condtion\n"); 460187712Srajerr2: 461187712Sraj if (err_msg) 462228660Sdim fprintf(stderr, "%s", err_msg); 463187712Sraj 464187712Sraj close(fd); 465187712Sraj return (1); 466187712Sraj} 467187712Sraj 468187712Srajint 469187712Srajmain(int argc, char** argv) 470187712Sraj{ 471187712Sraj struct iiccmd cmd; 472187712Sraj struct options i2c_opt; 473230356Seadler char *dev, *skip_addr, *i2c_buf; 474187712Sraj int error, chunk_size, i, j, ch; 475187712Sraj 476187712Sraj errno = 0; 477187712Sraj error = 0; 478187712Sraj 479187712Sraj /* Line-break the output every chunk_size bytes */ 480187712Sraj chunk_size = 16; 481187712Sraj 482187712Sraj dev = I2C_DEV; 483187712Sraj 484187712Sraj /* Default values */ 485187712Sraj i2c_opt.addr_set = 0; 486187712Sraj i2c_opt.off = 0; 487187712Sraj i2c_opt.verbose = 0; 488187712Sraj i2c_opt.dir = 'r'; /* direction = read */ 489187712Sraj i2c_opt.width = 8; 490187712Sraj i2c_opt.count = 1; 491187712Sraj i2c_opt.binary = 0; /* ASCII text output */ 492187712Sraj i2c_opt.scan = 0; /* no bus scan */ 493187712Sraj i2c_opt.skip = 0; /* scan all addresses */ 494187712Sraj i2c_opt.reset = 0; /* no bus reset */ 495187712Sraj i2c_opt.mode = I2C_MODE_NOTSET; 496187712Sraj 497187712Sraj while ((ch = getopt(argc, argv, "a:f:d:o:w:c:m:n:sbvrh")) != -1) { 498187712Sraj switch(ch) { 499187712Sraj case 'a': 500187712Sraj i2c_opt.addr = (strtoul(optarg, 0, 16) << 1); 501187712Sraj if (i2c_opt.addr == 0 && errno == EINVAL) 502187712Sraj i2c_opt.addr_set = 0; 503187712Sraj else 504187712Sraj i2c_opt.addr_set = 1; 505187712Sraj break; 506187712Sraj case 'f': 507187712Sraj dev = optarg; 508187712Sraj break; 509187712Sraj case 'd': 510187712Sraj i2c_opt.dir = optarg[0]; 511187712Sraj break; 512187712Sraj case 'o': 513187712Sraj i2c_opt.off = strtoul(optarg, 0, 16); 514187712Sraj if (i2c_opt.off == 0 && errno == EINVAL) 515187712Sraj error = 1; 516187712Sraj break; 517187712Sraj case 'w': 518187712Sraj i2c_opt.width = atoi(optarg); 519187712Sraj break; 520187712Sraj case 'c': 521187712Sraj i2c_opt.count = atoi(optarg); 522187712Sraj break; 523187712Sraj case 'm': 524187712Sraj if (!strcmp(optarg, "no")) 525187712Sraj i2c_opt.mode = I2C_MODE_NONE; 526187712Sraj else if (!strcmp(optarg, "ss")) 527187712Sraj i2c_opt.mode = I2C_MODE_STOP_START; 528187712Sraj else if (!strcmp(optarg, "rs")) 529187712Sraj i2c_opt.mode = I2C_MODE_REPEATED_START; 530187712Sraj else 531187712Sraj usage(); 532187712Sraj break; 533187712Sraj case 'n': 534187712Sraj i2c_opt.skip = 1; 535187712Sraj skip_addr = optarg; 536187712Sraj break; 537187712Sraj case 's': 538187712Sraj i2c_opt.scan = 1; 539187712Sraj break; 540187712Sraj case 'b': 541187712Sraj i2c_opt.binary = 1; 542187712Sraj break; 543187712Sraj case 'v': 544187712Sraj i2c_opt.verbose = 1; 545187712Sraj break; 546187712Sraj case 'r': 547187712Sraj i2c_opt.reset = 1; 548187712Sraj break; 549187712Sraj case 'h': 550187712Sraj default: 551187712Sraj usage(); 552187712Sraj } 553187712Sraj } 554187712Sraj argc -= optind; 555187712Sraj argv += optind; 556187712Sraj 557187712Sraj /* Set default mode if option -m is not specified */ 558187712Sraj if (i2c_opt.mode == I2C_MODE_NOTSET) { 559187712Sraj if (i2c_opt.dir == 'r') 560187712Sraj i2c_opt.mode = I2C_MODE_STOP_START; 561187712Sraj else if (i2c_opt.dir == 'w') 562187712Sraj i2c_opt.mode = I2C_MODE_NONE; 563187712Sraj } 564187712Sraj 565187712Sraj /* Basic sanity check of command line arguments */ 566187712Sraj if (i2c_opt.scan) { 567187712Sraj if (i2c_opt.addr_set) 568187712Sraj usage(); 569187712Sraj } else if (i2c_opt.reset) { 570187712Sraj if (i2c_opt.addr_set) 571187712Sraj usage(); 572187712Sraj } else if (error) { 573187712Sraj usage(); 574187712Sraj } else if ((i2c_opt.dir == 'r' || i2c_opt.dir == 'w')) { 575187712Sraj if ((i2c_opt.addr_set == 0) || 576187712Sraj !(i2c_opt.width == 0 || i2c_opt.width == 8 || 577187712Sraj i2c_opt.width == 16)) 578187712Sraj usage(); 579187712Sraj } 580187712Sraj 581187712Sraj if (i2c_opt.verbose) 582187712Sraj fprintf(stderr, "dev: %s, addr: 0x%x, r/w: %c, " 583187712Sraj "offset: 0x%02x, width: %u, count: %u\n", dev, 584187712Sraj i2c_opt.addr >> 1, i2c_opt.dir, i2c_opt.off, 585187712Sraj i2c_opt.width, i2c_opt.count); 586187712Sraj 587187712Sraj if (i2c_opt.scan) 588187712Sraj exit(scan_bus(cmd, dev, i2c_opt.skip, skip_addr)); 589187712Sraj 590187712Sraj if (i2c_opt.reset) 591187712Sraj exit(reset_bus(cmd, dev)); 592187712Sraj 593187712Sraj i2c_buf = malloc(i2c_opt.count); 594187712Sraj if (i2c_buf == NULL) 595187712Sraj err(1, "data malloc"); 596187712Sraj 597187712Sraj if (i2c_opt.dir == 'w') { 598187712Sraj error = i2c_write(dev, i2c_opt, i2c_buf); 599187712Sraj if (error) { 600187712Sraj free(i2c_buf); 601187712Sraj return (1); 602187712Sraj } 603187712Sraj } 604187712Sraj if (i2c_opt.dir == 'r') { 605187712Sraj error = i2c_read(dev, i2c_opt, i2c_buf); 606187712Sraj if (error) { 607187712Sraj free(i2c_buf); 608187712Sraj return (1); 609187712Sraj } 610187712Sraj } 611187712Sraj 612187712Sraj if (i2c_opt.verbose) 613187712Sraj fprintf(stderr, "\nData %s (hex):\n", i2c_opt.dir == 'r' ? 614187712Sraj "read" : "written"); 615187712Sraj 616187712Sraj i = 0; 617187712Sraj j = 0; 618187712Sraj while (i < i2c_opt.count) { 619187712Sraj if (i2c_opt.verbose || (i2c_opt.dir == 'r' && 620187712Sraj !i2c_opt.binary)) 621187712Sraj fprintf (stderr, "%02hhx ", i2c_buf[i++]); 622187712Sraj 623187712Sraj if (i2c_opt.dir == 'r' && i2c_opt.binary) { 624187712Sraj fprintf(stdout, "%c", i2c_buf[j++]); 625187712Sraj if(!i2c_opt.verbose) 626187712Sraj i++; 627187712Sraj } 628187712Sraj if (!i2c_opt.verbose && (i2c_opt.dir == 'w')) 629187712Sraj break; 630187712Sraj if ((i % chunk_size) == 0) 631187712Sraj fprintf(stderr, "\n"); 632187712Sraj } 633187712Sraj if ((i % chunk_size) != 0) 634187712Sraj fprintf(stderr, "\n"); 635187712Sraj 636187712Sraj free(i2c_buf); 637187712Sraj return (0); 638187712Sraj} 639