1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (C) 2008-2009 Semihalf, Michal Hajduk and Bartlomiej Sieka 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <assert.h> 33 #include <ctype.h> 34 #include <err.h> 35 #include <errno.h> 36 #include <sysexits.h> 37 #include <fcntl.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 #include <sys/endian.h> 43 #include <sys/ioctl.h> 44 45 #include <dev/iicbus/iic.h> 46 47 #define I2C_DEV "/dev/iic0" 48 #define I2C_MODE_NOTSET 0 49 #define I2C_MODE_NONE 1 50 #define I2C_MODE_STOP_START 2 51 #define I2C_MODE_REPEATED_START 3 52 #define I2C_MODE_TRANSFER 4 53 54 struct options { 55 const char *width; 56 unsigned count; 57 int verbose; 58 int binary; 59 const char *skip; 60 int mode; 61 char dir; 62 uint32_t addr; 63 uint32_t off; 64 uint8_t off_buf[2]; 65 size_t off_len; 66 }; 67 68 __dead2 static void 69 usage(const char *msg) 70 { 71 72 if (msg != NULL) 73 fprintf(stderr, "%s\n", msg); 74 fprintf(stderr, "usage: %s -a addr [-f device] [-d [r|w]] [-o offset] " 75 "[-w [0|8|16|16LE|16BE]] [-c count] [-m [tr|ss|rs|no]] [-b] [-v]\n", 76 getprogname()); 77 fprintf(stderr, " %s -s [-f device] [-n skip_addr] -v\n", 78 getprogname()); 79 fprintf(stderr, " %s -r [-f device] -v\n", getprogname()); 80 exit(EX_USAGE); 81 } 82 83 static int 84 i2c_do_stop(int fd) 85 { 86 int i; 87 88 i = ioctl(fd, I2CSTOP); 89 if (i < 0) 90 fprintf(stderr, "ioctl: error sending stop condition: %s\n", 91 strerror(errno)); 92 return (i); 93 } 94 95 static int 96 i2c_do_start(int fd, struct iiccmd *cmd) 97 { 98 int i; 99 100 i = ioctl(fd, I2CSTART, cmd); 101 if (i < 0) 102 fprintf(stderr, "ioctl: error sending start condition: %s\n", 103 strerror(errno)); 104 return (i); 105 } 106 107 static int 108 i2c_do_repeatstart(int fd, struct iiccmd *cmd) 109 { 110 int i; 111 112 i = ioctl(fd, I2CRPTSTART, cmd); 113 if (i < 0) 114 fprintf(stderr, "ioctl: error sending repeated start: %s\n", 115 strerror(errno)); 116 return (i); 117 } 118 119 static int 120 i2c_do_write(int fd, struct iiccmd *cmd) 121 { 122 int i; 123 124 i = ioctl(fd, I2CWRITE, cmd); 125 if (i < 0) 126 fprintf(stderr, "ioctl: error writing: %s\n", 127 strerror(errno)); 128 return (i); 129 } 130 131 static int 132 i2c_do_read(int fd, struct iiccmd *cmd) 133 { 134 int i; 135 136 i = ioctl(fd, I2CREAD, cmd); 137 if (i < 0) 138 fprintf(stderr, "ioctl: error reading: %s\n", 139 strerror(errno)); 140 return (i); 141 } 142 143 static int 144 i2c_do_reset(int fd) 145 { 146 struct iiccmd cmd; 147 int i; 148 149 memset(&cmd, 0, sizeof cmd); 150 i = ioctl(fd, I2CRSTCARD, &cmd); 151 if (i < 0) 152 fprintf(stderr, "ioctl: error resetting controller: %s\n", 153 strerror(errno)); 154 return (i); 155 } 156 157 static void 158 parse_skip(const char *skip, char blacklist[128]) 159 { 160 const char *p; 161 unsigned x, y; 162 163 for (p = skip; *p != '\0';) { 164 if (*p == '0' && p[1] == 'x') 165 p += 2; 166 if (!isxdigit(*p)) 167 usage("Bad -n argument, expected (first) hex-digit"); 168 x = digittoint(*p++) << 4; 169 if (!isxdigit(*p)) 170 usage("Bad -n argument, expected (second) hex-digit"); 171 x |= digittoint(*p++); 172 if (x == 0 || x > 0x7f) 173 usage("Bad -n argument, (01..7f)"); 174 if (*p == ':' || *p == ',' || *p == '\0') { 175 blacklist[x] = 1; 176 if (*p != '\0') 177 p++; 178 continue; 179 } 180 if (*p == '-') { 181 p++; 182 } else if (*p == '.' && p[1] == '.') { 183 p += 2; 184 } else { 185 usage("Bad -n argument, ([:|,|..|-])"); 186 } 187 if (*p == '0' && p[1] == 'x') 188 p += 2; 189 if (!isxdigit(*p)) 190 usage("Bad -n argument, expected (first) hex-digit"); 191 y = digittoint(*p++) << 4; 192 if (!isxdigit(*p)) 193 usage("Bad -n argument, expected (second) hex-digit"); 194 y |= digittoint(*p++); 195 if (y == 0 || y > 0x7f) 196 usage("Bad -n argument, (01..7f)"); 197 if (y < x) 198 usage("Bad -n argument, (end < start)"); 199 for (;x <= y; x++) 200 blacklist[x] = 1; 201 if (*p == ':' || *p == ',') 202 p++; 203 } 204 } 205 206 static int 207 scan_bus(const char *dev, int fd, const char *skip, int verbose) 208 { 209 struct iiccmd cmd; 210 struct iic_msg rdmsg; 211 struct iic_rdwr_data rdwrdata; 212 int error; 213 unsigned u; 214 int num_found = 0, use_read_xfer; 215 uint8_t rdbyte; 216 char blacklist[128]; 217 const char *sep = ""; 218 219 memset(blacklist, 0, sizeof blacklist); 220 221 if (skip != NULL) 222 parse_skip(skip, blacklist); 223 224 for (use_read_xfer = 0; use_read_xfer < 2; use_read_xfer++) { 225 for (u = 1; u < 127; u++) { 226 if (blacklist[u]) 227 continue; 228 229 cmd.slave = u << 1; 230 cmd.last = 1; 231 cmd.count = 0; 232 if (i2c_do_reset(fd)) 233 return (EX_NOINPUT); 234 235 if (use_read_xfer) { 236 rdmsg.buf = &rdbyte; 237 rdmsg.len = 1; 238 rdmsg.flags = IIC_M_RD; 239 rdmsg.slave = u << 1; 240 rdwrdata.msgs = &rdmsg; 241 rdwrdata.nmsgs = 1; 242 error = ioctl(fd, I2CRDWR, &rdwrdata); 243 } else { 244 error = ioctl(fd, I2CSTART, &cmd); 245 if (errno == ENODEV || errno == EOPNOTSUPP) 246 break; /* Try reads instead */ 247 (void)ioctl(fd, I2CSTOP); 248 } 249 if (error == 0) { 250 if (!num_found++ && verbose) { 251 fprintf(stderr, 252 "Scanning I2C devices on %s:\n", 253 dev); 254 } 255 printf("%s%02x", sep, u); 256 sep = " "; 257 } 258 } 259 if (num_found > 0) 260 break; 261 if (verbose && !use_read_xfer) 262 fprintf(stderr, 263 "Hardware may not support START/STOP scanning; " 264 "trying less-reliable read method.\n"); 265 } 266 if (num_found == 0 && verbose) 267 printf("<Nothing Found>"); 268 269 printf("\n"); 270 271 return (i2c_do_reset(fd)); 272 } 273 274 static int 275 reset_bus(const char *dev, int fd, int verbose) 276 { 277 278 if (verbose) 279 fprintf(stderr, "Resetting I2C controller on %s\n", dev); 280 return (i2c_do_reset(fd)); 281 } 282 283 static const char * 284 encode_offset(const char *width, unsigned address, uint8_t *dst, size_t *len) 285 { 286 287 if (!strcmp(width, "0")) { 288 *len = 0; 289 return (NULL); 290 } 291 if (!strcmp(width, "8")) { 292 if (address > 0xff) 293 return ("Invalid 8-bit address\n"); 294 *dst = address; 295 *len = 1; 296 return (NULL); 297 } 298 if (address > 0xffff) 299 return ("Invalid 16-bit address\n"); 300 if (!strcmp(width, "16LE") || !strcmp(width, "16")) { 301 le16enc(dst, address); 302 *len = 2; 303 return (NULL); 304 } 305 if (!strcmp(width, "16BE")) { 306 be16enc(dst, address); 307 *len = 2; 308 return (NULL); 309 } 310 return ("Invalid offset width, must be: 0|8|16|16LE|16BE\n"); 311 } 312 313 static int 314 write_offset(int fd, struct options i2c_opt, struct iiccmd *cmd) 315 { 316 317 if (i2c_opt.off_len > 0) { 318 cmd->count = i2c_opt.off_len; 319 cmd->buf = (void*)i2c_opt.off_buf; 320 return (i2c_do_write(fd, cmd)); 321 } 322 return (0); 323 } 324 325 static int 326 i2c_write(int fd, struct options i2c_opt, uint8_t *i2c_buf) 327 { 328 struct iiccmd cmd; 329 char buf[i2c_opt.off_len + i2c_opt.count]; 330 331 memset(&cmd, 0, sizeof(cmd)); 332 cmd.slave = i2c_opt.addr; 333 334 if (i2c_do_start(fd, &cmd)) 335 return (i2c_do_stop(fd) | 1); 336 337 switch(i2c_opt.mode) { 338 case I2C_MODE_STOP_START: 339 if (write_offset(fd, i2c_opt, &cmd)) 340 return (i2c_do_stop(fd) | 1); 341 342 if (i2c_do_stop(fd)) 343 return (1); 344 345 if (i2c_do_start(fd, &cmd)) 346 return (i2c_do_stop(fd) | 1); 347 348 /* 349 * Write the data 350 */ 351 cmd.count = i2c_opt.count; 352 cmd.buf = (void*)i2c_buf; 353 cmd.last = 0; 354 if (i2c_do_write(fd, &cmd)) 355 return (i2c_do_stop(fd) | 1); 356 break; 357 358 case I2C_MODE_REPEATED_START: 359 if (write_offset(fd, i2c_opt, &cmd)) 360 return (i2c_do_stop(fd) | 1); 361 362 if (i2c_do_repeatstart(fd, &cmd)) 363 return (i2c_do_stop(fd) | 1); 364 365 /* 366 * Write the data 367 */ 368 cmd.count = i2c_opt.count; 369 cmd.buf = (void*)i2c_buf; 370 cmd.last = 0; 371 if (i2c_do_write(fd, &cmd)) 372 return (i2c_do_stop(fd) | 1); 373 break; 374 375 case I2C_MODE_NONE: /* fall through */ 376 default: 377 memcpy(buf, i2c_opt.off_buf, i2c_opt.off_len); 378 memcpy(buf + i2c_opt.off_len, i2c_buf, i2c_opt.count); 379 /* 380 * Write offset and data 381 */ 382 cmd.count = i2c_opt.off_len + i2c_opt.count; 383 cmd.buf = (void*)buf; 384 cmd.last = 0; 385 if (i2c_do_write(fd, &cmd)) 386 return (i2c_do_stop(fd) | 1); 387 break; 388 } 389 390 return (i2c_do_stop(fd)); 391 } 392 393 static int 394 i2c_read(int fd, struct options i2c_opt, uint8_t *i2c_buf) 395 { 396 struct iiccmd cmd; 397 char data = 0; 398 399 memset(&cmd, 0, sizeof(cmd)); 400 cmd.slave = i2c_opt.addr; 401 402 if (i2c_opt.off_len) { 403 cmd.count = 1; 404 cmd.last = 0; 405 cmd.buf = &data; 406 if (i2c_do_start(fd, &cmd)) 407 return (i2c_do_stop(fd) | 1); 408 409 if (write_offset(fd, i2c_opt, &cmd)) 410 return (i2c_do_stop(fd) | 1); 411 412 if (i2c_opt.mode == I2C_MODE_STOP_START && i2c_do_stop(fd)) 413 return (1); 414 } 415 cmd.slave = i2c_opt.addr | 1; 416 cmd.count = 1; 417 cmd.last = 0; 418 cmd.buf = &data; 419 if (i2c_opt.mode == I2C_MODE_STOP_START || i2c_opt.off_len == 0) { 420 if (i2c_do_start(fd, &cmd)) 421 return (i2c_do_stop(fd) | 1); 422 } else if (i2c_opt.mode == I2C_MODE_REPEATED_START) { 423 if (i2c_do_repeatstart(fd, &cmd)) 424 return (i2c_do_stop(fd) | 1); 425 } 426 427 cmd.count = i2c_opt.count; 428 cmd.buf = (void*)i2c_buf; 429 cmd.last = 1; 430 if (i2c_do_read(fd, &cmd)) 431 return (i2c_do_stop(fd) | 1); 432 433 return (i2c_do_stop(fd)); 434 } 435 436 /* 437 * i2c_rdwr_transfer() - use I2CRDWR to conduct a complete i2c transfer. 438 * 439 * Some i2c hardware is unable to provide direct control over START, REPEAT- 440 * START, and STOP operations. Such hardware can only perform a complete 441 * START-<data>-STOP or START-<data>-REPEAT-START-<data>-STOP sequence as a 442 * single operation. The driver framework refers to this sequence as a 443 * "transfer" so we call it "transfer mode". We assemble either one or two 444 * iic_msg structures to describe the IO operations, and hand them off to the 445 * driver to be handled as a single transfer. 446 */ 447 static int 448 i2c_rdwr_transfer(int fd, struct options i2c_opt, uint8_t *i2c_buf) 449 { 450 struct iic_msg msgs[2], *msgp = msgs; 451 struct iic_rdwr_data xfer; 452 int flag = 0; 453 454 if (i2c_opt.off_len) { 455 msgp->flags = IIC_M_WR | IIC_M_NOSTOP; 456 msgp->slave = i2c_opt.addr; 457 msgp->buf = i2c_opt.off_buf; 458 msgp->len = i2c_opt.off_len; 459 msgp++; 460 flag = IIC_M_NOSTART; 461 } 462 463 /* 464 * If the transfer direction is write and we did a write of the offset 465 * above, then we need to elide the start; this transfer is just more 466 * writing that follows the one started above. For a read, we always do 467 * a start; if we did an offset write above it'll be a repeat-start 468 * because of the NOSTOP flag used above. 469 */ 470 if (i2c_opt.dir == 'w') 471 msgp->flags = IIC_M_WR | flag; 472 else 473 msgp->flags = IIC_M_RD; 474 msgp->slave = i2c_opt.addr; 475 msgp->len = i2c_opt.count; 476 msgp->buf = i2c_buf; 477 msgp++; 478 479 xfer.msgs = msgs; 480 xfer.nmsgs = msgp - msgs; 481 482 if (ioctl(fd, I2CRDWR, &xfer) == -1 ) 483 err(1, "ioctl(I2CRDWR) failed"); 484 485 return (0); 486 } 487 488 static int 489 access_bus(int fd, struct options i2c_opt) 490 { 491 uint8_t i2c_buf[i2c_opt.count]; 492 int error; 493 unsigned u, chunk_size = 16; 494 495 /* 496 * For a write, read the data to be written to the chip from stdin. 497 */ 498 if (i2c_opt.dir == 'w') { 499 if (i2c_opt.verbose && !i2c_opt.binary) 500 fprintf(stderr, "Enter %u bytes of data: ", 501 i2c_opt.count); 502 if (fread(i2c_buf, 1, i2c_opt.count, stdin) != i2c_opt.count) 503 err(1, "not enough data, exiting\n"); 504 } 505 506 if (i2c_opt.mode == I2C_MODE_TRANSFER) 507 error = i2c_rdwr_transfer(fd, i2c_opt, i2c_buf); 508 else if (i2c_opt.dir == 'w') 509 error = i2c_write(fd, i2c_opt, i2c_buf); 510 else 511 error = i2c_read(fd, i2c_opt, i2c_buf); 512 513 if (error == 0) { 514 if (i2c_opt.dir == 'r' && i2c_opt.binary) { 515 (void)fwrite(i2c_buf, 1, i2c_opt.count, stdout); 516 } else if (i2c_opt.verbose || i2c_opt.dir == 'r') { 517 if (i2c_opt.verbose) 518 fprintf(stderr, "\nData %s (hex):\n", 519 i2c_opt.dir == 'r' ? "read" : "written"); 520 521 for (u = 0; u < i2c_opt.count; u++) { 522 printf("%02hhx ", i2c_buf[u]); 523 if ((u % chunk_size) == chunk_size - 1) 524 printf("\n"); 525 } 526 if ((u % chunk_size) != 0) 527 printf("\n"); 528 } 529 } 530 531 return (error); 532 } 533 534 int 535 main(int argc, char** argv) 536 { 537 struct options i2c_opt; 538 const char *dev, *err_msg; 539 int fd, error = 0, ch; 540 const char *optflags = "a:f:d:o:w:c:m:n:sbvrh"; 541 char do_what = 0; 542 543 dev = I2C_DEV; 544 545 /* Default values */ 546 i2c_opt.off = 0; 547 i2c_opt.verbose = 0; 548 i2c_opt.dir = 'r'; /* direction = read */ 549 i2c_opt.width = "8"; 550 i2c_opt.count = 1; 551 i2c_opt.binary = 0; /* ASCII text output */ 552 i2c_opt.skip = NULL; /* scan all addresses */ 553 i2c_opt.mode = I2C_MODE_NOTSET; 554 555 /* Find out what we are going to do */ 556 557 while ((ch = getopt(argc, argv, "a:f:d:o:w:c:m:n:sbvrh")) != -1) { 558 switch(ch) { 559 case 'a': 560 case 'r': 561 case 's': 562 if (do_what) 563 usage("Only one of [-a|-h|-r|-s]"); 564 do_what = ch; 565 break; 566 case 'h': 567 usage("Help:"); 568 break; 569 default: 570 break; 571 } 572 } 573 574 /* Then handle the legal subset of arguments */ 575 576 switch (do_what) { 577 case 0: usage("Pick one of [-a|-h|-r|-s]"); break; 578 case 'a': optflags = "a:f:d:w:o:c:m:bv"; break; 579 case 'r': optflags = "rf:v"; break; 580 case 's': optflags = "sf:n:v"; break; 581 default: assert("Bad do_what"); 582 } 583 584 optreset = 1; 585 optind = 1; 586 587 while ((ch = getopt(argc, argv, optflags)) != -1) { 588 switch(ch) { 589 case 'a': 590 i2c_opt.addr = strtoul(optarg, 0, 16); 591 if (i2c_opt.addr == 0 && errno == EINVAL) 592 usage("Bad -a argument (hex)"); 593 if (i2c_opt.addr == 0 || i2c_opt.addr > 0x7f) 594 usage("Bad -a argument (01..7f)"); 595 i2c_opt.addr <<= 1; 596 break; 597 case 'f': 598 dev = optarg; 599 break; 600 case 'd': 601 if (strcmp(optarg, "r") && strcmp(optarg, "w")) 602 usage("Bad -d argument ([r|w])"); 603 i2c_opt.dir = optarg[0]; 604 break; 605 case 'o': 606 i2c_opt.off = strtoul(optarg, 0, 16); 607 if (i2c_opt.off == 0 && errno == EINVAL) 608 usage("Bad -o argument (hex)"); 609 break; 610 case 'w': 611 i2c_opt.width = optarg; // checked later. 612 break; 613 case 'c': 614 i2c_opt.count = (strtoul(optarg, 0, 10)); 615 if (i2c_opt.count == 0 && errno == EINVAL) 616 usage("Bad -c argument (decimal)"); 617 break; 618 case 'm': 619 if (!strcmp(optarg, "no")) 620 i2c_opt.mode = I2C_MODE_NONE; 621 else if (!strcmp(optarg, "ss")) 622 i2c_opt.mode = I2C_MODE_STOP_START; 623 else if (!strcmp(optarg, "rs")) 624 i2c_opt.mode = I2C_MODE_REPEATED_START; 625 else if (!strcmp(optarg, "tr")) 626 i2c_opt.mode = I2C_MODE_TRANSFER; 627 else 628 usage("Bad -m argument ([no|ss|rs|tr])"); 629 break; 630 case 'n': 631 i2c_opt.skip = optarg; 632 break; 633 case 's': break; 634 case 'b': 635 i2c_opt.binary = 1; 636 break; 637 case 'v': 638 i2c_opt.verbose = 1; 639 break; 640 case 'r': break; 641 default: 642 fprintf(stderr, "Illegal -%c option", ch); 643 usage(NULL); 644 } 645 } 646 argc -= optind; 647 argv += optind; 648 if (argc > 0) 649 usage("Too many arguments"); 650 651 /* Set default mode if option -m is not specified */ 652 if (i2c_opt.mode == I2C_MODE_NOTSET) { 653 if (i2c_opt.dir == 'r') 654 i2c_opt.mode = I2C_MODE_STOP_START; 655 else if (i2c_opt.dir == 'w') 656 i2c_opt.mode = I2C_MODE_NONE; 657 } 658 659 err_msg = encode_offset(i2c_opt.width, i2c_opt.off, 660 i2c_opt.off_buf, &i2c_opt.off_len); 661 if (err_msg != NULL) { 662 fprintf(stderr, "%s", err_msg); 663 exit(EX_USAGE); 664 } 665 666 if (i2c_opt.verbose) 667 fprintf(stderr, "dev: %s, addr: 0x%x, r/w: %c, " 668 "offset: 0x%02x, width: %s, count: %u\n", dev, 669 i2c_opt.addr >> 1, i2c_opt.dir, i2c_opt.off, 670 i2c_opt.width, i2c_opt.count); 671 672 fd = open(dev, O_RDWR); 673 if (fd == -1) { 674 fprintf(stderr, "Error opening I2C controller (%s): %s\n", 675 dev, strerror(errno)); 676 return (EX_NOINPUT); 677 } 678 679 switch (do_what) { 680 case 's': 681 error = scan_bus(dev, fd, i2c_opt.skip, i2c_opt.verbose); 682 break; 683 case 'r': 684 error = reset_bus(dev, fd, i2c_opt.verbose); 685 break; 686 case 'a': 687 error = access_bus(fd, i2c_opt); 688 break; 689 default: 690 assert("Bad do_what"); 691 } 692 693 ch = close(fd); 694 assert(ch == 0); 695 return (error); 696 } 697