busybox/miscutils/i2c_tools.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * Minimal i2c-tools implementation for busybox.
   4 * Parts of code ported from i2c-tools:
   5 *              http://www.lm-sensors.org/wiki/I2CTools.
   6 *
   7 * Copyright (C) 2014 by Bartosz Golaszewski <bartekgola@gmail.com>
   8 *
   9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  10 */
  11//config:config I2CGET
  12//config:       bool "i2cget (5.5 kb)"
  13//config:       default y
  14//config:       select PLATFORM_LINUX
  15//config:       help
  16//config:       Read from I2C/SMBus chip registers.
  17//config:
  18//config:config I2CSET
  19//config:       bool "i2cset (6.7 kb)"
  20//config:       default y
  21//config:       select PLATFORM_LINUX
  22//config:       help
  23//config:       Set I2C registers.
  24//config:
  25//config:config I2CDUMP
  26//config:       bool "i2cdump (7.1 kb)"
  27//config:       default y
  28//config:       select PLATFORM_LINUX
  29//config:       help
  30//config:       Examine I2C registers.
  31//config:
  32//config:config I2CDETECT
  33//config:       bool "i2cdetect (7.1 kb)"
  34//config:       default y
  35//config:       select PLATFORM_LINUX
  36//config:       help
  37//config:       Detect I2C chips.
  38//config:
  39//config:config I2CTRANSFER
  40//config:       bool "i2ctransfer (4.0 kb)"
  41//config:       default y
  42//config:       select PLATFORM_LINUX
  43//config:       help
  44//config:       Send user-defined I2C messages in one transfer.
  45//config:
  46
  47//applet:IF_I2CGET(APPLET(i2cget, BB_DIR_USR_SBIN, BB_SUID_DROP))
  48//applet:IF_I2CSET(APPLET(i2cset, BB_DIR_USR_SBIN, BB_SUID_DROP))
  49//applet:IF_I2CDUMP(APPLET(i2cdump, BB_DIR_USR_SBIN, BB_SUID_DROP))
  50//applet:IF_I2CDETECT(APPLET(i2cdetect, BB_DIR_USR_SBIN, BB_SUID_DROP))
  51//applet:IF_I2CTRANSFER(APPLET(i2ctransfer, BB_DIR_USR_SBIN, BB_SUID_DROP))
  52/* not NOEXEC: if hw operation stalls, use less memory in "hung" process */
  53
  54//kbuild:lib-$(CONFIG_I2CGET) += i2c_tools.o
  55//kbuild:lib-$(CONFIG_I2CSET) += i2c_tools.o
  56//kbuild:lib-$(CONFIG_I2CDUMP) += i2c_tools.o
  57//kbuild:lib-$(CONFIG_I2CDETECT) += i2c_tools.o
  58//kbuild:lib-$(CONFIG_I2CTRANSFER) += i2c_tools.o
  59
  60/*
  61 * Unsupported stuff:
  62 *
  63 * - upstream i2c-tools can also look-up i2c busses by name, we only accept
  64 *   numbers,
  65 * - bank and bankreg parameters for i2cdump are not supported because of
  66 *   their limited usefulness (see i2cdump manual entry for more info),
  67 * - i2cdetect doesn't look for bus info in /proc as it does in upstream, but
  68 *   it shouldn't be a problem in modern kernels.
  69 */
  70
  71#include "libbb.h"
  72
  73#include <linux/i2c.h>
  74
  75#define I2CDUMP_NUM_REGS                256
  76
  77#define I2CDETECT_MODE_AUTO             0
  78#define I2CDETECT_MODE_QUICK            1
  79#define I2CDETECT_MODE_READ             2
  80
  81/* linux/i2c-dev.h from i2c-tools overwrites the one from linux uapi
  82 * and defines symbols already defined by linux/i2c.h.
  83 * Also, it defines a bunch of static inlines which we would rather NOT
  84 * inline. What a mess.
  85 * We need only these definitions from linux/i2c-dev.h:
  86 */
  87#define I2C_SLAVE                       0x0703
  88#define I2C_SLAVE_FORCE                 0x0706
  89#define I2C_FUNCS                       0x0705
  90#define I2C_PEC                         0x0708
  91#define I2C_SMBUS                       0x0720
  92#define I2C_RDWR                        0x0707
  93#define I2C_RDWR_IOCTL_MAX_MSGS         42
  94#define I2C_RDWR_IOCTL_MAX_MSGS_STR     "42"
  95struct i2c_smbus_ioctl_data {
  96        __u8 read_write;
  97        __u8 command;
  98        __u32 size;
  99        union i2c_smbus_data *data;
 100};
 101struct i2c_rdwr_ioctl_data {
 102        struct i2c_msg *msgs;   /* pointers to i2c_msgs */
 103        __u32 nmsgs;            /* number of i2c_msgs */
 104};
 105/* end linux/i2c-dev.h */
 106
 107/*
 108 * This is needed for ioctl_or_perror_and_die() since it only accepts pointers.
 109 */
 110static ALWAYS_INLINE void *itoptr(int i)
 111{
 112        return (void*)(intptr_t)i;
 113}
 114
 115static int32_t i2c_smbus_access(int fd, char read_write, uint8_t cmd,
 116                                int size, union i2c_smbus_data *data)
 117{
 118        struct i2c_smbus_ioctl_data args;
 119
 120        args.read_write = read_write;
 121        args.command = cmd;
 122        args.size = size;
 123        args.data = data;
 124
 125        return ioctl(fd, I2C_SMBUS, &args);
 126}
 127
 128static int32_t i2c_smbus_read_byte(int fd)
 129{
 130        union i2c_smbus_data data;
 131        int err;
 132
 133        err = i2c_smbus_access(fd, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data);
 134        if (err < 0)
 135                return err;
 136
 137        return data.byte;
 138}
 139
 140#if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP
 141static int32_t i2c_smbus_write_byte(int fd, uint8_t val)
 142{
 143        return i2c_smbus_access(fd, I2C_SMBUS_WRITE,
 144                                val, I2C_SMBUS_BYTE, NULL);
 145}
 146
 147static int32_t i2c_smbus_read_byte_data(int fd, uint8_t cmd)
 148{
 149        union i2c_smbus_data data;
 150        int err;
 151
 152        err = i2c_smbus_access(fd, I2C_SMBUS_READ, cmd,
 153                               I2C_SMBUS_BYTE_DATA, &data);
 154        if (err < 0)
 155                return err;
 156
 157        return data.byte;
 158}
 159
 160static int32_t i2c_smbus_read_word_data(int fd, uint8_t cmd)
 161{
 162        union i2c_smbus_data data;
 163        int err;
 164
 165        err = i2c_smbus_access(fd, I2C_SMBUS_READ, cmd,
 166                               I2C_SMBUS_WORD_DATA, &data);
 167        if (err < 0)
 168                return err;
 169
 170        return data.word;
 171}
 172#endif /* ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP */
 173
 174#if ENABLE_I2CSET
 175static int32_t i2c_smbus_write_byte_data(int file,
 176                                         uint8_t cmd, uint8_t value)
 177{
 178        union i2c_smbus_data data;
 179
 180        data.byte = value;
 181
 182        return i2c_smbus_access(file, I2C_SMBUS_WRITE, cmd,
 183                                I2C_SMBUS_BYTE_DATA, &data);
 184}
 185
 186static int32_t i2c_smbus_write_word_data(int file, uint8_t cmd, uint16_t value)
 187{
 188        union i2c_smbus_data data;
 189
 190        data.word = value;
 191
 192        return i2c_smbus_access(file, I2C_SMBUS_WRITE, cmd,
 193                                I2C_SMBUS_WORD_DATA, &data);
 194}
 195
 196static int32_t i2c_smbus_write_block_data(int file, uint8_t cmd,
 197                                   uint8_t length, const uint8_t *values)
 198{
 199        union i2c_smbus_data data;
 200
 201        if (length > I2C_SMBUS_BLOCK_MAX)
 202                length = I2C_SMBUS_BLOCK_MAX;
 203
 204        memcpy(data.block+1, values, length);
 205        data.block[0] = length;
 206
 207        return i2c_smbus_access(file, I2C_SMBUS_WRITE, cmd,
 208                                I2C_SMBUS_BLOCK_DATA, &data);
 209}
 210
 211static int32_t i2c_smbus_write_i2c_block_data(int file, uint8_t cmd,
 212                                       uint8_t length, const uint8_t *values)
 213{
 214        union i2c_smbus_data data;
 215
 216        if (length > I2C_SMBUS_BLOCK_MAX)
 217                length = I2C_SMBUS_BLOCK_MAX;
 218
 219        memcpy(data.block+1, values, length);
 220        data.block[0] = length;
 221
 222        return i2c_smbus_access(file, I2C_SMBUS_WRITE, cmd,
 223                                I2C_SMBUS_I2C_BLOCK_BROKEN, &data);
 224}
 225#endif /* ENABLE_I2CSET */
 226
 227#if ENABLE_I2CDUMP
 228/*
 229 * Returns the number of bytes read, vals must hold at
 230 * least I2C_SMBUS_BLOCK_MAX bytes.
 231 */
 232static int32_t i2c_smbus_read_block_data(int fd, uint8_t cmd, uint8_t *vals)
 233{
 234        union i2c_smbus_data data;
 235        int i, err;
 236
 237        err = i2c_smbus_access(fd, I2C_SMBUS_READ, cmd,
 238                               I2C_SMBUS_BLOCK_DATA, &data);
 239        if (err < 0)
 240                return err;
 241
 242        for (i = 1; i <= data.block[0]; i++)
 243                *vals++ = data.block[i];
 244        return data.block[0];
 245}
 246
 247static int32_t i2c_smbus_read_i2c_block_data(int fd, uint8_t cmd,
 248                                             uint8_t len, uint8_t *vals)
 249{
 250        union i2c_smbus_data data;
 251        int i, err;
 252
 253        if (len > I2C_SMBUS_BLOCK_MAX)
 254                len = I2C_SMBUS_BLOCK_MAX;
 255        data.block[0] = len;
 256
 257        err = i2c_smbus_access(fd, I2C_SMBUS_READ, cmd,
 258                               len == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN :
 259                                           I2C_SMBUS_I2C_BLOCK_DATA, &data);
 260        if (err < 0)
 261                return err;
 262
 263        for (i = 1; i <= data.block[0]; i++)
 264                *vals++ = data.block[i];
 265        return data.block[0];
 266}
 267#endif /* ENABLE_I2CDUMP */
 268
 269#if ENABLE_I2CDETECT
 270static int32_t i2c_smbus_write_quick(int fd, uint8_t val)
 271{
 272        return i2c_smbus_access(fd, val, 0, I2C_SMBUS_QUICK, NULL);
 273}
 274#endif /* ENABLE_I2CDETECT */
 275
 276static int i2c_bus_lookup(const char *bus_str)
 277{
 278        return xstrtou_range(bus_str, 10, 0, 0xfffff);
 279}
 280
 281#if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP || ENABLE_I2CTRANSFER
 282static int i2c_parse_bus_addr(const char *addr_str)
 283{
 284        /* Slave address must be in range 0x03 - 0x77. */
 285        return xstrtou_range(addr_str, 16, 0x03, 0x77);
 286}
 287
 288static void i2c_set_pec(int fd, int pec)
 289{
 290        ioctl_or_perror_and_die(fd, I2C_PEC,
 291                                itoptr(pec ? 1 : 0),
 292                                "can't set PEC");
 293}
 294
 295static void i2c_set_slave_addr(int fd, int addr, int force)
 296{
 297        ioctl_or_perror_and_die(fd, force ? I2C_SLAVE_FORCE : I2C_SLAVE,
 298                                itoptr(addr),
 299                                "can't set address to 0x%02x", addr);
 300}
 301#endif /* ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP */
 302
 303#if ENABLE_I2CGET || ENABLE_I2CSET
 304static int i2c_parse_data_addr(const char *data_addr)
 305{
 306        /* Data address must be an 8 bit integer. */
 307        return xstrtou_range(data_addr, 16, 0, 0xff);
 308}
 309#endif /* ENABLE_I2CGET || ENABLE_I2CSET */
 310
 311/*
 312 * Opens the device file associated with given i2c bus.
 313 *
 314 * Upstream i2c-tools also support opening devices by i2c bus name
 315 * but we drop it here for size reduction.
 316 */
 317static int i2c_dev_open(int i2cbus)
 318{
 319        char filename[sizeof("/dev/i2c-%d") + sizeof(int)*3];
 320        int fd;
 321
 322        sprintf(filename, "/dev/i2c-%d", i2cbus);
 323        fd = open(filename, O_RDWR);
 324        if (fd < 0) {
 325                if (errno == ENOENT) {
 326                        filename[8] = '/'; /* change to "/dev/i2c/%d" */
 327                        fd = xopen(filename, O_RDWR);
 328                } else {
 329                        bb_perror_msg_and_die("can't open '%s'", filename);
 330                }
 331        }
 332
 333        return fd;
 334}
 335
 336/* Size reducing helpers for xxx_check_funcs(). */
 337static void get_funcs_matrix(int fd, unsigned long *funcs)
 338{
 339        ioctl_or_perror_and_die(fd, I2C_FUNCS, funcs,
 340                        "can't get adapter functionality matrix");
 341}
 342
 343#if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP
 344static void check_funcs_test_end(int funcs, int pec, const char *err)
 345{
 346        if (pec && !(funcs & (I2C_FUNC_SMBUS_PEC | I2C_FUNC_I2C)))
 347                bb_error_msg("warning: adapter does not support PEC");
 348
 349        if (err)
 350                bb_error_msg_and_die(
 351                        "adapter has no %s capability", err);
 352}
 353#endif /* ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP */
 354
 355/*
 356 * The below functions emit an error message and exit if the adapter doesn't
 357 * support desired functionalities.
 358 */
 359#if ENABLE_I2CGET || ENABLE_I2CDUMP
 360static void check_read_funcs(int fd, int mode, int data_addr, int pec)
 361{
 362        unsigned long funcs;
 363        const char *err = NULL;
 364
 365        get_funcs_matrix(fd, &funcs);
 366        switch (mode) {
 367        case I2C_SMBUS_BYTE:
 368                if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE)) {
 369                        err = "SMBus receive byte";
 370                        break;
 371                }
 372                if (data_addr >= 0 && !(funcs & I2C_FUNC_SMBUS_WRITE_BYTE))
 373                        err = "SMBus send byte";
 374                break;
 375        case I2C_SMBUS_BYTE_DATA:
 376                if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE_DATA))
 377                        err = "SMBus read byte";
 378                break;
 379        case I2C_SMBUS_WORD_DATA:
 380                if (!(funcs & I2C_FUNC_SMBUS_READ_WORD_DATA))
 381                        err = "SMBus read word";
 382                break;
 383#if ENABLE_I2CDUMP
 384        case I2C_SMBUS_BLOCK_DATA:
 385                if (!(funcs & I2C_FUNC_SMBUS_READ_BLOCK_DATA))
 386                        err = "SMBus block read";
 387                break;
 388
 389        case I2C_SMBUS_I2C_BLOCK_DATA:
 390                if (!(funcs & I2C_FUNC_SMBUS_READ_I2C_BLOCK))
 391                        err = "I2C block read";
 392                break;
 393#endif /* ENABLE_I2CDUMP */
 394        default:
 395                bb_error_msg_and_die("internal error");
 396        }
 397        check_funcs_test_end(funcs, pec, err);
 398}
 399#endif /* ENABLE_I2CGET || ENABLE_I2CDUMP */
 400
 401#if ENABLE_I2CSET
 402static void check_write_funcs(int fd, int mode, int pec)
 403{
 404        unsigned long funcs;
 405        const char *err = NULL;
 406
 407        get_funcs_matrix(fd, &funcs);
 408        switch (mode) {
 409        case I2C_SMBUS_BYTE:
 410                if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE))
 411                        err = "SMBus send byte";
 412                break;
 413
 414        case I2C_SMBUS_BYTE_DATA:
 415                if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
 416                        err = "SMBus write byte";
 417                break;
 418
 419        case I2C_SMBUS_WORD_DATA:
 420                if (!(funcs & I2C_FUNC_SMBUS_WRITE_WORD_DATA))
 421                        err = "SMBus write word";
 422                break;
 423
 424        case I2C_SMBUS_BLOCK_DATA:
 425                if (!(funcs & I2C_FUNC_SMBUS_WRITE_BLOCK_DATA))
 426                        err = "SMBus block write";
 427                break;
 428        case I2C_SMBUS_I2C_BLOCK_DATA:
 429                if (!(funcs & I2C_FUNC_SMBUS_WRITE_I2C_BLOCK))
 430                        err = "I2C block write";
 431                break;
 432        }
 433        check_funcs_test_end(funcs, pec, err);
 434}
 435#endif /* ENABLE_I2CSET */
 436
 437static void confirm_or_abort(void)
 438{
 439        fprintf(stderr, "Continue? [y/N] ");
 440        if (!bb_ask_y_confirmation())
 441                bb_error_msg_and_die("aborting");
 442}
 443
 444/*
 445 * Return only if user confirms the action, abort otherwise.
 446 *
 447 * The messages displayed here are much less elaborate than their i2c-tools
 448 * counterparts - this is done for size reduction.
 449 */
 450static void confirm_action(int bus_addr, int mode, int data_addr, int pec)
 451{
 452        bb_error_msg("WARNING! This program can confuse your I2C bus");
 453
 454        /* Don't let the user break his/her EEPROMs */
 455        if (bus_addr >= 0x50 && bus_addr <= 0x57 && pec) {
 456                bb_error_msg_and_die("this is I2C not smbus - using PEC on I2C "
 457                        "devices may result in data loss, aborting");
 458        }
 459
 460        if (mode == I2C_SMBUS_BYTE && data_addr >= 0 && pec)
 461                bb_error_msg("WARNING! May interpret a write byte command "
 462                        "with PEC as a write byte data command");
 463
 464        if (pec)
 465                bb_error_msg("PEC checking enabled");
 466
 467        confirm_or_abort();
 468}
 469
 470#if ENABLE_I2CGET
 471//usage:#define i2cget_trivial_usage
 472//usage:       "[-fy] BUS CHIP-ADDRESS [DATA-ADDRESS [MODE]]"
 473//usage:#define i2cget_full_usage "\n\n"
 474//usage:       "Read from I2C/SMBus chip registers"
 475//usage:     "\n"
 476//usage:     "\n        I2CBUS  I2C bus number"
 477//usage:     "\n        ADDRESS 0x03-0x77"
 478//usage:     "\nMODE is:"
 479//usage:     "\n        b       Read byte data (default)"
 480//usage:     "\n        w       Read word data"
 481//usage:     "\n        c       Write byte/read byte"
 482//usage:     "\n        Append p for SMBus PEC"
 483//usage:     "\n"
 484//usage:     "\n        -f      Force access"
 485//usage:     "\n        -y      Disable interactive mode"
 486int i2cget_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 487int i2cget_main(int argc UNUSED_PARAM, char **argv)
 488{
 489        const unsigned opt_f = (1 << 0), opt_y = (1 << 1);
 490
 491        int bus_num, bus_addr, data_addr = -1, status;
 492        int mode = I2C_SMBUS_BYTE, pec = 0, fd;
 493        unsigned opts;
 494
 495        opts = getopt32(argv, "^" "fy" "\0" "-2:?4"/*from 2 to 4 args*/);
 496        argv += optind;
 497
 498        bus_num = i2c_bus_lookup(argv[0]);
 499        bus_addr = i2c_parse_bus_addr(argv[1]);
 500
 501        if (argv[2]) {
 502                data_addr = i2c_parse_data_addr(argv[2]);
 503                mode = I2C_SMBUS_BYTE_DATA;
 504                if (argv[3]) {
 505                        switch (argv[3][0]) {
 506                        case 'b':       /* Already set */               break;
 507                        case 'w':       mode = I2C_SMBUS_WORD_DATA;     break;
 508                        case 'c':       mode = I2C_SMBUS_BYTE;          break;
 509                        default:
 510                                bb_error_msg("invalid mode");
 511                                bb_show_usage();
 512                        }
 513                        pec = argv[3][1] == 'p';
 514                }
 515        }
 516
 517        fd = i2c_dev_open(bus_num);
 518        check_read_funcs(fd, mode, data_addr, pec);
 519        i2c_set_slave_addr(fd, bus_addr, opts & opt_f);
 520
 521        if (!(opts & opt_y))
 522                confirm_action(bus_addr, mode, data_addr, pec);
 523
 524        if (pec)
 525                i2c_set_pec(fd, 1);
 526
 527        switch (mode) {
 528        case I2C_SMBUS_BYTE:
 529                if (data_addr >= 0) {
 530                        status = i2c_smbus_write_byte(fd, data_addr);
 531                        if (status < 0)
 532                                bb_error_msg("warning - write failed");
 533                }
 534                status = i2c_smbus_read_byte(fd);
 535                break;
 536        case I2C_SMBUS_WORD_DATA:
 537                status = i2c_smbus_read_word_data(fd, data_addr);
 538                break;
 539        default: /* I2C_SMBUS_BYTE_DATA */
 540                status = i2c_smbus_read_byte_data(fd, data_addr);
 541        }
 542        close(fd);
 543
 544        if (status < 0)
 545                bb_perror_msg_and_die("read failed");
 546
 547        printf("0x%0*x\n", mode == I2C_SMBUS_WORD_DATA ? 4 : 2, status);
 548
 549        return 0;
 550}
 551#endif /* ENABLE_I2CGET */
 552
 553#if ENABLE_I2CSET
 554//usage:#define i2cset_trivial_usage
 555//usage:       "[-fy] [-m MASK] BUS CHIP-ADDRESS DATA-ADDRESS [VALUE] ... [MODE]"
 556//usage:#define i2cset_full_usage "\n\n"
 557//usage:       "Set I2C registers"
 558//usage:     "\n"
 559//usage:     "\n        I2CBUS  I2C bus number"
 560//usage:     "\n        ADDRESS 0x03-0x77"
 561//usage:     "\nMODE is:"
 562//usage:     "\n        c       Byte, no value"
 563//usage:     "\n        b       Byte data (default)"
 564//usage:     "\n        w       Word data"
 565//usage:     "\n        i       I2C block data"
 566//usage:     "\n        s       SMBus block data"
 567//usage:     "\n        Append p for SMBus PEC"
 568//usage:     "\n"
 569//usage:     "\n        -f      Force access"
 570//usage:     "\n        -y      Disable interactive mode"
 571//usage:     "\n        -r      Read back and compare the result"
 572//usage:     "\n        -m MASK Mask specifying which bits to write"
 573int i2cset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 574int i2cset_main(int argc, char **argv)
 575{
 576        const unsigned opt_f = (1 << 0), opt_y = (1 << 1),
 577                              opt_m = (1 << 2), opt_r = (1 << 3);
 578
 579        int bus_num, bus_addr, data_addr, mode = I2C_SMBUS_BYTE, pec = 0;
 580        int val, blen, mask, fd, status;
 581        unsigned char block[I2C_SMBUS_BLOCK_MAX];
 582        char *opt_m_arg = NULL;
 583        unsigned opts;
 584
 585        opts = getopt32(argv, "^"
 586                "fym:r"
 587                "\0" "-3", /* minimum 3 args */
 588                &opt_m_arg
 589        );
 590        argv += optind;
 591        argc -= optind;
 592        argc--; /* now argv[argc] is last arg */
 593
 594        bus_num = i2c_bus_lookup(argv[0]);
 595        bus_addr = i2c_parse_bus_addr(argv[1]);
 596        data_addr = i2c_parse_data_addr(argv[2]);
 597
 598        if (argv[3]) {
 599                if (!argv[4] && argv[3][0] != 'c') {
 600                        mode = I2C_SMBUS_BYTE_DATA; /* Implicit b */
 601                } else {
 602                        switch (argv[argc][0]) {
 603                        case 'c': /* Already set */
 604                                break;
 605                        case 'b': mode = I2C_SMBUS_BYTE_DATA;
 606                                break;
 607                        case 'w': mode = I2C_SMBUS_WORD_DATA;
 608                                break;
 609                        case 's': mode = I2C_SMBUS_BLOCK_DATA;
 610                                break;
 611                        case 'i': mode = I2C_SMBUS_I2C_BLOCK_DATA;
 612                                break;
 613                        default:
 614                                bb_error_msg("invalid mode");
 615                                bb_show_usage();
 616                        }
 617
 618                        pec = (argv[argc][1] == 'p');
 619                        if (mode == I2C_SMBUS_BLOCK_DATA
 620                         || mode == I2C_SMBUS_I2C_BLOCK_DATA
 621                        ) {
 622                                if (pec && mode == I2C_SMBUS_I2C_BLOCK_DATA)
 623                                        bb_error_msg_and_die(
 624                                                "PEC not supported for I2C "
 625                                                "block writes");
 626                                if (opts & opt_m)
 627                                        bb_error_msg_and_die(
 628                                                "mask not supported for block "
 629                                                "writes");
 630                        }
 631                }
 632        }
 633
 634        /* Prepare the value(s) to be written according to current mode. */
 635        mask = 0;
 636        blen = 0;
 637        switch (mode) {
 638        case I2C_SMBUS_BYTE_DATA:
 639                val = xstrtou_range(argv[3], 0, 0, 0xff);
 640                break;
 641        case I2C_SMBUS_WORD_DATA:
 642                val = xstrtou_range(argv[3], 0, 0, 0xffff);
 643                break;
 644        case I2C_SMBUS_BLOCK_DATA:
 645        case I2C_SMBUS_I2C_BLOCK_DATA:
 646                for (blen = 3; blen < argc; blen++)
 647                        block[blen - 3] = xstrtou_range(argv[blen], 0, 0, 0xff);
 648                blen -= 3;
 649                val = -1;
 650                break;
 651        default:
 652                val = -1;
 653                break;
 654        }
 655
 656        if (opts & opt_m) {
 657                mask = xstrtou_range(opt_m_arg, 0, 0,
 658                                (mode == I2C_SMBUS_BYTE ||
 659                                 mode == I2C_SMBUS_BYTE_DATA) ? 0xff : 0xffff);
 660        }
 661
 662        fd = i2c_dev_open(bus_num);
 663        check_write_funcs(fd, mode, pec);
 664        i2c_set_slave_addr(fd, bus_addr, opts & opt_f);
 665
 666        if (!(opts & opt_y))
 667                confirm_action(bus_addr, mode, data_addr, pec);
 668
 669        /*
 670         * If we're using mask - read the current value here and adjust the
 671         * value to be written.
 672         */
 673        if (opts & opt_m) {
 674                int tmpval;
 675
 676                switch (mode) {
 677                case I2C_SMBUS_BYTE:
 678                        tmpval = i2c_smbus_read_byte(fd);
 679                        break;
 680                case I2C_SMBUS_WORD_DATA:
 681                        tmpval = i2c_smbus_read_word_data(fd, data_addr);
 682                        break;
 683                default:
 684                        tmpval = i2c_smbus_read_byte_data(fd, data_addr);
 685                }
 686
 687                if (tmpval < 0)
 688                        bb_perror_msg_and_die("can't read old value");
 689
 690                val = (val & mask) | (tmpval & ~mask);
 691
 692                if (!(opts & opt_y)) {
 693                        bb_error_msg("old value 0x%0*x, write mask "
 694                                "0x%0*x, will write 0x%0*x to register "
 695                                "0x%02x",
 696                                mode == I2C_SMBUS_WORD_DATA ? 4 : 2, tmpval,
 697                                mode == I2C_SMBUS_WORD_DATA ? 4 : 2, mask,
 698                                mode == I2C_SMBUS_WORD_DATA ? 4 : 2, val,
 699                                data_addr);
 700                        confirm_or_abort();
 701                }
 702        }
 703
 704        if (pec)
 705                i2c_set_pec(fd, 1);
 706
 707        switch (mode) {
 708        case I2C_SMBUS_BYTE:
 709                status = i2c_smbus_write_byte(fd, data_addr);
 710                break;
 711        case I2C_SMBUS_WORD_DATA:
 712                status = i2c_smbus_write_word_data(fd, data_addr, val);
 713                break;
 714        case I2C_SMBUS_BLOCK_DATA:
 715                status = i2c_smbus_write_block_data(fd, data_addr,
 716                                                    blen, block);
 717                break;
 718        case I2C_SMBUS_I2C_BLOCK_DATA:
 719                status = i2c_smbus_write_i2c_block_data(fd, data_addr,
 720                                                        blen, block);
 721                break;
 722        default: /* I2C_SMBUS_BYTE_DATA */
 723                status = i2c_smbus_write_byte_data(fd, data_addr, val);
 724                break;
 725        }
 726        if (status < 0)
 727                bb_perror_msg_and_die("write failed");
 728
 729        if (pec)
 730                i2c_set_pec(fd, 0); /* Clear PEC. */
 731
 732        /* No readback required - we're done. */
 733        if (!(opts & opt_r))
 734                return 0;
 735
 736        switch (mode) {
 737        case I2C_SMBUS_BYTE:
 738                status = i2c_smbus_read_byte(fd);
 739                val = data_addr;
 740                break;
 741        case I2C_SMBUS_WORD_DATA:
 742                status = i2c_smbus_read_word_data(fd, data_addr);
 743                break;
 744        default: /* I2C_SMBUS_BYTE_DATA */
 745                status = i2c_smbus_read_byte_data(fd, data_addr);
 746        }
 747
 748        if (status < 0) {
 749                puts("Warning - readback failed");
 750        } else
 751        if (status != val) {
 752                printf("Warning - data mismatch - wrote "
 753                       "0x%0*x, read back 0x%0*x\n",
 754                       mode == I2C_SMBUS_WORD_DATA ? 4 : 2, val,
 755                       mode == I2C_SMBUS_WORD_DATA ? 4 : 2, status);
 756        } else {
 757                printf("Value 0x%0*x written, readback matched\n",
 758                       mode == I2C_SMBUS_WORD_DATA ? 4 : 2, val);
 759        }
 760
 761        return 0;
 762}
 763#endif /* ENABLE_I2CSET */
 764
 765#if ENABLE_I2CDUMP
 766static int read_block_data(int buf_fd, int mode, int *block)
 767{
 768        uint8_t cblock[I2C_SMBUS_BLOCK_MAX + I2CDUMP_NUM_REGS];
 769        int res, blen = 0, tmp, i;
 770
 771        if (mode == I2C_SMBUS_BLOCK_DATA) {
 772                blen = i2c_smbus_read_block_data(buf_fd, 0, cblock);
 773                if (blen <= 0)
 774                        goto fail;
 775        } else {
 776                for (res = 0; res < I2CDUMP_NUM_REGS; res += tmp) {
 777                        tmp = i2c_smbus_read_i2c_block_data(
 778                                        buf_fd, res, I2C_SMBUS_BLOCK_MAX,
 779                                        cblock + res);
 780                        if (tmp <= 0) {
 781                                blen = tmp;
 782                                goto fail;
 783                        }
 784                }
 785
 786                if (res >= I2CDUMP_NUM_REGS)
 787                        res = I2CDUMP_NUM_REGS;
 788
 789                for (i = 0; i < res; i++)
 790                        block[i] = cblock[i];
 791
 792                if (mode != I2C_SMBUS_BLOCK_DATA)
 793                        for (i = res; i < I2CDUMP_NUM_REGS; i++)
 794                                block[i] = -1;
 795        }
 796
 797        return blen;
 798
 799 fail:
 800        bb_error_msg_and_die("block read failed: %d", blen);
 801}
 802
 803/* Dump all but word data. */
 804static void dump_data(int bus_fd, int mode, unsigned first,
 805                      unsigned last, int *block, int blen)
 806{
 807        int i, j, res;
 808
 809        puts("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f"
 810             "    0123456789abcdef");
 811
 812        for (i = 0; i < I2CDUMP_NUM_REGS; i += 0x10) {
 813                if (mode == I2C_SMBUS_BLOCK_DATA && i >= blen)
 814                        break;
 815                if (i/16 < first/16)
 816                        continue;
 817                if (i/16 > last/16)
 818                        break;
 819
 820                printf("%02x: ", i);
 821                for (j = 0; j < 16; j++) {
 822                        fflush_all();
 823                        /* Skip unwanted registers */
 824                        if (i+j < first || i+j > last) {
 825                                printf("   ");
 826                                if (mode == I2C_SMBUS_WORD_DATA) {
 827                                        printf("   ");
 828                                        j++;
 829                                }
 830                                continue;
 831                        }
 832
 833                        switch (mode) {
 834                        case I2C_SMBUS_BYTE_DATA:
 835                                res = i2c_smbus_read_byte_data(bus_fd, i+j);
 836                                block[i+j] = res;
 837                                break;
 838                        case I2C_SMBUS_WORD_DATA:
 839                                res = i2c_smbus_read_word_data(bus_fd, i+j);
 840                                if (res < 0) {
 841                                        block[i+j] = res;
 842                                        block[i+j+1] = res;
 843                                } else {
 844                                        block[i+j] = res & 0xff;
 845                                        block[i+j+1] = res >> 8;
 846                                }
 847                                break;
 848                        case I2C_SMBUS_BYTE:
 849                                res = i2c_smbus_read_byte(bus_fd);
 850                                block[i+j] = res;
 851                                break;
 852                        default:
 853                                res = block[i+j];
 854                        }
 855
 856                        if (mode == I2C_SMBUS_BLOCK_DATA &&
 857                            i+j >= blen) {
 858                                printf("   ");
 859                        } else if (res < 0) {
 860                                printf("XX ");
 861                                if (mode == I2C_SMBUS_WORD_DATA)
 862                                        printf("XX ");
 863                        } else {
 864                                printf("%02x ", block[i+j]);
 865                                if (mode == I2C_SMBUS_WORD_DATA)
 866                                        printf("%02x ", block[i+j+1]);
 867                        }
 868
 869                        if (mode == I2C_SMBUS_WORD_DATA)
 870                                j++;
 871                }
 872                printf("   ");
 873
 874                for (j = 0; j < 16; j++) {
 875                        if (mode == I2C_SMBUS_BLOCK_DATA && i+j >= blen)
 876                                break;
 877                        /* Skip unwanted registers */
 878                        if (i+j < first || i+j > last) {
 879                                bb_putchar(' ');
 880                                continue;
 881                        }
 882
 883                        res = block[i+j];
 884                        if (res < 0) {
 885                                bb_putchar('X');
 886                        } else if (res == 0x00 || res == 0xff) {
 887                                bb_putchar('.');
 888                        } else if (res < 32 || res >= 127) {
 889                                bb_putchar('?');
 890                        } else {
 891                                bb_putchar(res);
 892                        }
 893                }
 894                bb_putchar('\n');
 895        }
 896}
 897
 898static void dump_word_data(int bus_fd, unsigned first, unsigned last)
 899{
 900        int i, j, rv;
 901
 902        /* Word data. */
 903        puts("     0,8  1,9  2,a  3,b  4,c  5,d  6,e  7,f");
 904        for (i = 0; i < 256; i += 8) {
 905                if (i/8 < first/8)
 906                        continue;
 907                if (i/8 > last/8)
 908                        break;
 909
 910                printf("%02x: ", i);
 911                for (j = 0; j < 8; j++) {
 912                        /* Skip unwanted registers. */
 913                        if (i+j < first || i+j > last) {
 914                                printf("     ");
 915                                continue;
 916                        }
 917
 918                        rv = i2c_smbus_read_word_data(bus_fd, i+j);
 919                        if (rv < 0)
 920                                printf("XXXX ");
 921                        else
 922                                printf("%04x ", rv & 0xffff);
 923                }
 924                bb_putchar('\n');
 925        }
 926}
 927
 928//usage:#define i2cdump_trivial_usage
 929//usage:       "[-fy] [-r FIRST-LAST] BUS ADDR [MODE]"
 930//usage:#define i2cdump_full_usage "\n\n"
 931//usage:       "Examine I2C registers"
 932//usage:     "\n"
 933//usage:     "\n        I2CBUS  I2C bus number"
 934//usage:     "\n        ADDRESS 0x03-0x77"
 935//usage:     "\nMODE is:"
 936//usage:     "\n        b       Byte (default)"
 937//usage:     "\n        w       Word"
 938//usage:     "\n        W       Word on even register addresses"
 939//usage:     "\n        i       I2C block"
 940//usage:     "\n        s       SMBus block"
 941//usage:     "\n        c       Consecutive byte"
 942//usage:     "\n        Append p for SMBus PEC"
 943//usage:     "\n"
 944//usage:     "\n        -f      Force access"
 945//usage:     "\n        -y      Disable interactive mode"
 946//usage:     "\n        -r      Limit the number of registers being accessed"
 947int i2cdump_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 948int i2cdump_main(int argc UNUSED_PARAM, char **argv)
 949{
 950        const unsigned opt_f = (1 << 0), opt_y = (1 << 1),
 951                              opt_r = (1 << 2);
 952
 953        int bus_num, bus_addr, mode = I2C_SMBUS_BYTE_DATA, even = 0, pec = 0;
 954        unsigned first = 0x00, last = 0xff, opts;
 955        int block[I2CDUMP_NUM_REGS];
 956        char *opt_r_str, *dash;
 957        int fd, res;
 958
 959        opts = getopt32(argv, "^"
 960                "fyr:"
 961                "\0" "-2:?3" /* from 2 to 3 args */,
 962                &opt_r_str
 963        );
 964        argv += optind;
 965
 966        bus_num = i2c_bus_lookup(argv[0]);
 967        bus_addr = i2c_parse_bus_addr(argv[1]);
 968
 969        if (argv[2]) {
 970                switch (argv[2][0]) {
 971                case 'b': /* Already set. */                    break;
 972                case 'c': mode = I2C_SMBUS_BYTE;                break;
 973                case 'w': mode = I2C_SMBUS_WORD_DATA;           break;
 974                case 'W':
 975                        mode = I2C_SMBUS_WORD_DATA;
 976                        even = 1;
 977                        break;
 978                case 's': mode = I2C_SMBUS_BLOCK_DATA;          break;
 979                case 'i': mode = I2C_SMBUS_I2C_BLOCK_DATA;      break;
 980                default:
 981                        bb_error_msg_and_die("invalid mode");
 982                }
 983
 984                if (argv[2][1] == 'p') {
 985                        if (argv[2][0] == 'W' || argv[2][0] == 'i') {
 986                                bb_error_msg_and_die(
 987                                        "pec not supported for -W and -i");
 988                        } else {
 989                                pec = 1;
 990                        }
 991                }
 992        }
 993
 994        if (opts & opt_r) {
 995                first = strtol(opt_r_str, &dash, 0);
 996                if (dash == opt_r_str || *dash != '-' || first > 0xff)
 997                        bb_error_msg_and_die("invalid range");
 998                last = xstrtou_range(++dash, 0, first, 0xff);
 999
1000                /* Range is not available for every mode. */
1001                switch (mode) {
1002                case I2C_SMBUS_BYTE:
1003                case I2C_SMBUS_BYTE_DATA:
1004                        break;
1005                case I2C_SMBUS_WORD_DATA:
1006                        if (!even || (!(first % 2) && last % 2))
1007                                break;
1008                        /* Fall through */
1009                default:
1010                        bb_error_msg_and_die(
1011                                "range not compatible with selected mode");
1012                }
1013        }
1014
1015        fd = i2c_dev_open(bus_num);
1016        check_read_funcs(fd, mode, -1 /* data_addr */, pec);
1017        i2c_set_slave_addr(fd, bus_addr, opts & opt_f);
1018
1019        if (pec)
1020                i2c_set_pec(fd, 1);
1021
1022        if (!(opts & opt_y))
1023                confirm_action(bus_addr, mode, -1 /* data_addr */, pec);
1024
1025        /* All but word data. */
1026        if (mode != I2C_SMBUS_WORD_DATA || even) {
1027                int blen = 0;
1028
1029                if (mode == I2C_SMBUS_BLOCK_DATA || mode == I2C_SMBUS_I2C_BLOCK_DATA)
1030                        blen = read_block_data(fd, mode, block);
1031
1032                if (mode == I2C_SMBUS_BYTE) {
1033                        res = i2c_smbus_write_byte(fd, first);
1034                        if (res < 0)
1035                                bb_perror_msg_and_die("write start address");
1036                }
1037
1038                dump_data(fd, mode, first, last, block, blen);
1039        } else {
1040                dump_word_data(fd, first, last);
1041        }
1042
1043        return 0;
1044}
1045#endif /* ENABLE_I2CDUMP */
1046
1047#if ENABLE_I2CDETECT
1048enum adapter_type {
1049        ADT_DUMMY = 0,
1050        ADT_ISA,
1051        ADT_I2C,
1052        ADT_SMBUS,
1053};
1054
1055struct adap_desc {
1056        const char *funcs;
1057        const char *algo;
1058};
1059
1060static const struct adap_desc adap_descs[] = {
1061        { .funcs        = "dummy",
1062          .algo         = "Dummy bus", },
1063        { .funcs        = "isa",
1064          .algo         = "ISA bus", },
1065        { .funcs        = "i2c",
1066          .algo         = "I2C adapter", },
1067        { .funcs        = "smbus",
1068          .algo         = "SMBus adapter", },
1069};
1070
1071struct i2c_func
1072{
1073        long value;
1074        const char* name;
1075};
1076
1077static const struct i2c_func i2c_funcs_tab[] = {
1078        { .value = I2C_FUNC_I2C,
1079          .name = "I2C" },
1080        { .value = I2C_FUNC_SMBUS_QUICK,
1081          .name = "SMBus quick command" },
1082        { .value = I2C_FUNC_SMBUS_WRITE_BYTE,
1083          .name = "SMBus send byte" },
1084        { .value = I2C_FUNC_SMBUS_READ_BYTE,
1085          .name = "SMBus receive byte" },
1086        { .value = I2C_FUNC_SMBUS_WRITE_BYTE_DATA,
1087          .name = "SMBus write byte" },
1088        { .value = I2C_FUNC_SMBUS_READ_BYTE_DATA,
1089          .name = "SMBus read byte" },
1090        { .value = I2C_FUNC_SMBUS_WRITE_WORD_DATA,
1091          .name = "SMBus write word" },
1092        { .value = I2C_FUNC_SMBUS_READ_WORD_DATA,
1093          .name = "SMBus read word" },
1094        { .value = I2C_FUNC_SMBUS_PROC_CALL,
1095          .name = "SMBus process call" },
1096        { .value = I2C_FUNC_SMBUS_WRITE_BLOCK_DATA,
1097          .name = "SMBus block write" },
1098        { .value = I2C_FUNC_SMBUS_READ_BLOCK_DATA,
1099          .name = "SMBus block read" },
1100        { .value = I2C_FUNC_SMBUS_BLOCK_PROC_CALL,
1101          .name = "SMBus block process call" },
1102        { .value = I2C_FUNC_SMBUS_PEC,
1103          .name = "SMBus PEC" },
1104        { .value = I2C_FUNC_SMBUS_WRITE_I2C_BLOCK,
1105          .name = "I2C block write" },
1106        { .value = I2C_FUNC_SMBUS_READ_I2C_BLOCK,
1107          .name = "I2C block read" },
1108        { .value = 0, .name = NULL }
1109};
1110
1111static enum adapter_type i2cdetect_get_funcs(int bus)
1112{
1113        enum adapter_type ret;
1114        unsigned long funcs;
1115        int fd;
1116
1117        fd = i2c_dev_open(bus);
1118
1119        get_funcs_matrix(fd, &funcs);
1120        if (funcs & I2C_FUNC_I2C)
1121                ret = ADT_I2C;
1122        else if (funcs & (I2C_FUNC_SMBUS_BYTE |
1123                          I2C_FUNC_SMBUS_BYTE_DATA |
1124                          I2C_FUNC_SMBUS_WORD_DATA))
1125                ret = ADT_SMBUS;
1126        else
1127                ret = ADT_DUMMY;
1128
1129        close(fd);
1130
1131        return ret;
1132}
1133
1134static void NORETURN list_i2c_busses_and_exit(void)
1135{
1136        const char *const i2cdev_path = "/sys/class/i2c-dev";
1137
1138        char path[NAME_MAX], name[128];
1139        struct dirent *de, *subde;
1140        enum adapter_type adt;
1141        DIR *dir, *subdir;
1142        int rv, bus;
1143        char *pos;
1144        FILE *fp;
1145
1146        /*
1147         * XXX Upstream i2cdetect also looks for i2c bus info in /proc/bus/i2c,
1148         * but we won't bother since it's only useful on older kernels (before
1149         * 2.6.5). We expect sysfs to be present and mounted at /sys/.
1150         */
1151
1152        dir = xopendir(i2cdev_path);
1153        while ((de = readdir(dir))) {
1154                if (de->d_name[0] == '.')
1155                        continue;
1156
1157                /* Simple version for ISA chips. */
1158                snprintf(path, NAME_MAX, "%s/%s/name",
1159                         i2cdev_path, de->d_name);
1160                fp = fopen(path, "r");
1161                if (fp == NULL) {
1162                        snprintf(path, NAME_MAX,
1163                                 "%s/%s/device/name",
1164                                 i2cdev_path, de->d_name);
1165                        fp = fopen(path, "r");
1166                }
1167
1168                /* Non-ISA chips require the hard-way. */
1169                if (fp == NULL) {
1170                        snprintf(path, NAME_MAX,
1171                                 "%s/%s/device/name",
1172                                 i2cdev_path, de->d_name);
1173                        subdir = opendir(path);
1174                        if (subdir == NULL)
1175                                continue;
1176
1177                        while ((subde = readdir(subdir))) {
1178                                if (subde->d_name[0] == '.')
1179                                        continue;
1180
1181                                if (is_prefixed_with(subde->d_name, "i2c-")) {
1182                                        snprintf(path, NAME_MAX,
1183                                                 "%s/%s/device/%s/name",
1184                                                 i2cdev_path, de->d_name,
1185                                                 subde->d_name);
1186                                        fp = fopen(path, "r");
1187                                        break;
1188                                }
1189                        }
1190                }
1191
1192                if (fp != NULL) {
1193                        /*
1194                         * Get the rest of the info and display a line
1195                         * for a single bus.
1196                         */
1197                        memset(name, 0, sizeof(name));
1198                        pos = fgets(name, sizeof(name), fp);
1199                        fclose(fp);
1200                        if (pos == NULL)
1201                                continue;
1202
1203                        pos = strchr(name, '\n');
1204                        if (pos != NULL)
1205                                *pos = '\0';
1206
1207                        rv = sscanf(de->d_name, "i2c-%d", &bus);
1208                        if (rv != 1)
1209                                continue;
1210
1211                        if (is_prefixed_with(name, "ISA"))
1212                                adt = ADT_ISA;
1213                        else
1214                                adt = i2cdetect_get_funcs(bus);
1215
1216                        printf(
1217                                "i2c-%d\t%-10s\t%-32s\t%s\n",
1218                                bus, adap_descs[adt].funcs,
1219                                name, adap_descs[adt].algo);
1220                }
1221        }
1222
1223        exit(EXIT_SUCCESS);
1224}
1225
1226static void NORETURN no_support(const char *cmd)
1227{
1228        bb_error_msg_and_die("bus doesn't support %s", cmd);
1229}
1230
1231static void will_skip(const char *cmd)
1232{
1233        bb_error_msg(
1234                "warning: can't use %s command, "
1235                "will skip some addresses", cmd);
1236}
1237
1238//usage:#define i2cdetect_trivial_usage
1239//usage:       "-l | -F I2CBUS | [-ya] [-q|-r] I2CBUS [FIRST LAST]"
1240//usage:#define i2cdetect_full_usage "\n\n"
1241//usage:       "Detect I2C chips"
1242//usage:     "\n"
1243//usage:     "\n        -l      List installed buses"
1244//usage:     "\n        -F BUS# List functionalities on this bus"
1245//usage:     "\n        -y      Disable interactive mode"
1246//usage:     "\n        -a      Force scanning of non-regular addresses"
1247//usage:     "\n        -q      Use smbus quick write commands for probing (default)"
1248//usage:     "\n        -r      Use smbus read byte commands for probing"
1249//usage:     "\n        FIRST and LAST limit probing range"
1250int i2cdetect_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1251int i2cdetect_main(int argc UNUSED_PARAM, char **argv)
1252{
1253        const unsigned opt_y = (1 << 0), opt_a = (1 << 1),
1254                              opt_q = (1 << 2), opt_r = (1 << 3),
1255                              opt_F = (1 << 4), opt_l = (1 << 5);
1256
1257        int fd, bus_num, i, j, mode = I2CDETECT_MODE_AUTO, status, cmd;
1258        unsigned first = 0x03, last = 0x77, opts;
1259        unsigned long funcs;
1260
1261        opts = getopt32(argv, "^"
1262                        "yaqrFl"
1263                        "\0"
1264                        "q--r:r--q:"/*mutually exclusive*/
1265                        "?3"/*up to 3 args*/
1266        );
1267        argv += optind;
1268
1269        if (opts & opt_l)
1270                list_i2c_busses_and_exit();
1271
1272        if (!argv[0])
1273                bb_show_usage();
1274
1275        bus_num = i2c_bus_lookup(argv[0]);
1276        fd = i2c_dev_open(bus_num);
1277        get_funcs_matrix(fd, &funcs);
1278
1279        if (opts & opt_F) {
1280                /* Only list the functionalities. */
1281                printf("Functionalities implemented by bus #%d\n", bus_num);
1282                for (i = 0; i2c_funcs_tab[i].value; i++) {
1283                        printf("%-32s %s\n", i2c_funcs_tab[i].name,
1284                               funcs & i2c_funcs_tab[i].value ? "yes" : "no");
1285                }
1286
1287                return EXIT_SUCCESS;
1288        }
1289
1290        if (opts & opt_r)
1291                mode = I2CDETECT_MODE_READ;
1292        else if (opts & opt_q)
1293                mode = I2CDETECT_MODE_QUICK;
1294
1295        if (opts & opt_a) {
1296                first = 0x00;
1297                last = 0x7f;
1298        }
1299
1300        /* Read address range. */
1301        if (argv[1]) {
1302                first = xstrtou_range(argv[1], 16, first, last);
1303                if (argv[2])
1304                        last = xstrtou_range(argv[2], 16, first, last);
1305        }
1306
1307        if (!(funcs & (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_READ_BYTE))) {
1308                no_support("detection commands");
1309        } else
1310        if (mode == I2CDETECT_MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_QUICK)) {
1311                no_support("SMBus quick write");
1312        } else
1313        if (mode == I2CDETECT_MODE_READ && !(funcs & I2C_FUNC_SMBUS_READ_BYTE)) {
1314                no_support("SMBus receive byte");
1315        }
1316
1317        if (mode == I2CDETECT_MODE_AUTO) {
1318                if (!(funcs & I2C_FUNC_SMBUS_QUICK))
1319                        will_skip("SMBus quick write");
1320                if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE))
1321                        will_skip("SMBus receive byte");
1322        }
1323
1324        if (!(opts & opt_y))
1325                confirm_action(-1, -1, -1, 0);
1326
1327        puts("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f");
1328        for (i = 0; i < 128; i += 16) {
1329                printf("%02x: ", i);
1330                for (j = 0; j < 16; j++) {
1331                        fflush_all();
1332
1333                        cmd = mode;
1334                        if (mode == I2CDETECT_MODE_AUTO) {
1335                                if ((i+j >= 0x30 && i+j <= 0x37) ||
1336                                    (i+j >= 0x50 && i+j <= 0x5F))
1337                                        cmd = I2CDETECT_MODE_READ;
1338                                else
1339                                        cmd = I2CDETECT_MODE_QUICK;
1340                        }
1341
1342                        /* Skip unwanted addresses. */
1343                        if (i+j < first
1344                         || i+j > last
1345                         || (cmd == I2CDETECT_MODE_READ && !(funcs & I2C_FUNC_SMBUS_READ_BYTE))
1346                         || (cmd == I2CDETECT_MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_QUICK)))
1347                        {
1348                                printf("   ");
1349                                continue;
1350                        }
1351
1352                        status = ioctl(fd, I2C_SLAVE, itoptr(i + j));
1353                        if (status < 0) {
1354                                if (errno == EBUSY) {
1355                                        printf("UU ");
1356                                        continue;
1357                                }
1358
1359                                bb_perror_msg_and_die(
1360                                        "can't set address to 0x%02x", i + j);
1361                        }
1362
1363                        switch (cmd) {
1364                        case I2CDETECT_MODE_READ:
1365                                /*
1366                                 * This is known to lock SMBus on various
1367                                 * write-only chips (mainly clock chips).
1368                                 */
1369                                status = i2c_smbus_read_byte(fd);
1370                                break;
1371                        default: /* I2CDETECT_MODE_QUICK: */
1372                                /*
1373                                 * This is known to corrupt the Atmel
1374                                 * AT24RF08 EEPROM.
1375                                 */
1376                                status = i2c_smbus_write_quick(fd,
1377                                                               I2C_SMBUS_WRITE);
1378                                break;
1379                        }
1380
1381                        if (status < 0)
1382                                printf("-- ");
1383                        else
1384                                printf("%02x ", i+j);
1385                }
1386                bb_putchar('\n');
1387        }
1388
1389        return 0;
1390}
1391#endif /* ENABLE_I2CDETECT */
1392
1393#if ENABLE_I2CTRANSFER
1394static void check_i2c_func(int fd)
1395{
1396        unsigned long funcs;
1397
1398        get_funcs_matrix(fd, &funcs);
1399
1400        if (!(funcs & I2C_FUNC_I2C))
1401                bb_error_msg_and_die("adapter does not support I2C transfers");
1402}
1403
1404//usage:#define i2ctransfer_trivial_usage
1405//usage:       "[-fay] I2CBUS {rLENGTH[@ADDR] | wLENGTH[@ADDR] DATA...}..."
1406//usage:#define i2ctransfer_full_usage "\n\n"
1407//usage:       "Read/write I2C data in one transfer"
1408//usage:     "\n"
1409//usage:     "\n        -f      Force access to busy addresses"
1410//usage:     "\n        -a      Force access to non-regular addresses"
1411//usage:     "\n        -y      Disable interactive mode"
1412int i2ctransfer_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1413int i2ctransfer_main(int argc UNUSED_PARAM, char **argv)
1414{
1415        enum {
1416                opt_f = (1 << 0),
1417                opt_y = (1 << 1),
1418                opt_a = (1 << 2),
1419        };
1420        int bus_num, bus_addr;
1421        int fd;
1422        unsigned opts, first, last;
1423        int nmsgs, nmsgs_sent, i;
1424        struct i2c_msg msgs[I2C_RDWR_IOCTL_MAX_MSGS];
1425        struct i2c_rdwr_ioctl_data rdwr;
1426
1427        memset(msgs, 0, sizeof(msgs));
1428
1429        opts = getopt32(argv, "^"
1430                "fya"
1431                "\0" "-2" /* minimum 2 args */
1432        );
1433        first = 0x03;
1434        last = 0x77;
1435        if (opts & opt_a) {
1436                first = 0x00;
1437                last = 0x7f;
1438        }
1439
1440        argv += optind;
1441        bus_num = i2c_bus_lookup(argv[0]);
1442        fd = i2c_dev_open(bus_num);
1443        check_i2c_func(fd);
1444
1445        bus_addr = -1;
1446        nmsgs = 0;
1447        while (*++argv) {
1448                char *arg_ptr;
1449                unsigned len;
1450                uint16_t flags;
1451                char *end;
1452
1453                if (nmsgs >= I2C_RDWR_IOCTL_MAX_MSGS)
1454                        bb_error_msg_and_die("too many messages, max: "I2C_RDWR_IOCTL_MAX_MSGS_STR);
1455
1456                flags = 0;
1457                arg_ptr = *argv;
1458                switch (*arg_ptr++) {
1459                case 'r': flags |= I2C_M_RD; break;
1460                case 'w': break;
1461                default:
1462                        bb_show_usage();
1463                }
1464
1465                end = strchr(arg_ptr, '@');
1466                if (end) *end = '\0';
1467                len = xstrtou_range(arg_ptr, 0, 0, 0xffff);
1468                if (end) {
1469                        bus_addr = xstrtou_range(end + 1, 0, first, last);
1470                        i2c_set_slave_addr(fd, bus_addr, (opts & opt_f));
1471                } else {
1472                        /* Reuse last address if possible */
1473                        if (bus_addr < 0)
1474                                bb_error_msg_and_die("no address given in '%s'", *argv);
1475                }
1476
1477                msgs[nmsgs].addr = bus_addr;
1478                msgs[nmsgs].flags = flags;
1479                msgs[nmsgs].len = len;
1480                if (len)
1481                        msgs[nmsgs].buf = xzalloc(len);
1482
1483                if (!(flags & I2C_M_RD)) {
1484                        /* Consume DATA arg(s) */
1485                        unsigned buf_idx = 0;
1486
1487                        while (buf_idx < len) {
1488                                uint8_t data8;
1489                                unsigned long data;
1490
1491                                arg_ptr = *++argv;
1492                                if (!arg_ptr)
1493                                        bb_show_usage();
1494                                data = strtoul(arg_ptr, &end, 0);
1495                                if (data > 0xff || arg_ptr == end)
1496                                        bb_error_msg_and_die("invalid data byte '%s'", *argv);
1497
1498                                data8 = data;
1499                                while (buf_idx < len) {
1500                                        msgs[nmsgs].buf[buf_idx++] = data8;
1501                                        if (!*end)
1502                                                break;
1503                                        switch (*end) {
1504                                        /* Pseudo randomness (8 bit AXR with a=13 and b=27) */
1505                                        case 'p':
1506                                                data8 = (data8 ^ 27) + 13;
1507                                                data8 = (data8 << 1) | (data8 >> 7);
1508                                                break;
1509                                        case '+': data8++; break;
1510                                        case '-': data8--; break;
1511                                        case '=': break;
1512                                        default:
1513                                                bb_error_msg_and_die("invalid data byte suffix: '%s'",
1514                                                                     *argv);
1515                                        }
1516                                }
1517                        }
1518                }
1519                nmsgs++;
1520        }
1521
1522        if (!(opts & opt_y))
1523                confirm_action(bus_addr, 0, 0, 0);
1524
1525        rdwr.msgs = msgs;
1526        rdwr.nmsgs = nmsgs;
1527        nmsgs_sent = ioctl_or_perror_and_die(fd, I2C_RDWR, &rdwr, "I2C_RDWR");
1528        if (nmsgs_sent < nmsgs)
1529                bb_error_msg("warning: only %u/%u messages sent", nmsgs_sent, nmsgs);
1530
1531        for (i = 0; i < nmsgs_sent; i++) {
1532                if (msgs[i].len != 0 && (msgs[i].flags & I2C_M_RD)) {
1533                        int j;
1534                        for (j = 0; j < msgs[i].len - 1; j++)
1535                                printf("0x%02x ", msgs[i].buf[j]);
1536                        /* Print final byte with newline */
1537                        printf("0x%02x\n", msgs[i].buf[j]);
1538                }
1539        }
1540
1541# if ENABLE_FEATURE_CLEAN_UP
1542        close(fd);
1543        for (i = 0; i < nmsgs; i++)
1544                free(msgs[i].buf);
1545# endif
1546
1547        return 0;
1548}
1549#endif /* ENABLE_I2CTRANSFER */
1550