Example #1
0
int i2cdump_main(int argc UNUSED_PARAM, char **argv)
{
	const unsigned opt_f = (1 << 0), opt_y = (1 << 1),
			      opt_r = (1 << 2);
	const char *const optstr = "fyr:";

	int bus_num, bus_addr, mode = I2C_SMBUS_BYTE_DATA, even = 0, pec = 0;
	unsigned first = 0x00, last = 0xff, opts;
	int *block = (int *)bb_common_bufsiz1;
	char *opt_r_str, *dash;
	int fd, res;

        opt_complementary = "-2:?3"; /* from 2 to 3 args */
	opts = getopt32(argv, optstr, &opt_r_str);
	argv += optind;

	bus_num = i2c_bus_lookup(argv[0]);
	bus_addr = i2c_parse_bus_addr(argv[1]);

	if (argv[2]) {
		switch (argv[2][0]) {
		case 'b': /* Already set. */			break;
		case 'c': mode = I2C_SMBUS_BYTE;		break;
		case 'w': mode = I2C_SMBUS_WORD_DATA;		break;
		case 'W':
			mode = I2C_SMBUS_WORD_DATA;
			even = 1;
			break;
		case 's': mode = I2C_SMBUS_BLOCK_DATA;		break;
		case 'i': mode = I2C_SMBUS_I2C_BLOCK_DATA;	break;
		default:
			bb_error_msg_and_die("invalid mode");
		}

		if (argv[2][1] == 'p') {
			if (argv[2][0] == 'W' || argv[2][0] == 'i') {
				bb_error_msg_and_die(
					"pec not supported for -W and -i");
			} else {
				pec = 1;
			}
		}
	}

	if (opts & opt_r) {
		first = strtol(opt_r_str, &dash, 0);
		if (dash == opt_r_str || *dash != '-' || first > 0xff)
			bb_error_msg_and_die("invalid range");
		last = xstrtou_range(++dash, 0, first, 0xff);

		/* Range is not available for every mode. */
		switch (mode) {
		case I2C_SMBUS_BYTE:
		case I2C_SMBUS_BYTE_DATA:
			break;
		case I2C_SMBUS_WORD_DATA:
			if (!even || (!(first % 2) && last % 2))
				break;
			/* Fall through */
		default:
			bb_error_msg_and_die(
				"range not compatible with selected mode");
		}
	}

	fd = i2c_dev_open(bus_num);
	check_read_funcs(fd, mode, -1 /* data_addr */, pec);
	i2c_set_slave_addr(fd, bus_addr, opts & opt_f);

	if (pec)
		i2c_set_pec(fd, 1);

	if (!(opts & opt_y))
		confirm_action(bus_addr, mode, -1 /* data_addr */, pec);

	/* All but word data. */
	if (mode != I2C_SMBUS_WORD_DATA || even) {
		int blen = 0;

		if (mode == I2C_SMBUS_BLOCK_DATA || mode == I2C_SMBUS_I2C_BLOCK_DATA)
			blen = read_block_data(fd, mode, block);

		if (mode == I2C_SMBUS_BYTE) {
			res = i2c_smbus_write_byte(fd, first);
			if (res < 0)
				bb_perror_msg_and_die("write start address");
		}

		dump_data(fd, mode, first, last, block, blen);
	} else {
		dump_word_data(fd, first, last);
	}

	return 0;
}
Example #2
0
int i2cset_main(int argc, char **argv)
{
	const unsigned opt_f = (1 << 0), opt_y = (1 << 1),
			      opt_m = (1 << 2), opt_r = (1 << 3);
	const char *const optstr = "fym:r";

	int bus_num, bus_addr, data_addr, mode = I2C_SMBUS_BYTE, pec = 0;
	int val, blen = 0, mask = 0, fd, status;
	unsigned char block[I2C_SMBUS_BLOCK_MAX];
	char *opt_m_arg = NULL;
	unsigned opts;

        opt_complementary = "-3"; /* from 3 to ? args */
	opts = getopt32(argv, optstr, &opt_m_arg);
	argv += optind;
	argc -= optind;

	bus_num = i2c_bus_lookup(argv[0]);
	bus_addr = i2c_parse_bus_addr(argv[1]);
	data_addr = i2c_parse_data_addr(argv[2]);

	if (argv[3]) {
		if (!argv[4] && argv[3][0] != 'c') {
			mode = I2C_SMBUS_BYTE_DATA; /* Implicit b */
		} else {
			switch (argv[argc-1][0]) {
			case 'c': /* Already set */			break;
			case 'b': mode = I2C_SMBUS_BYTE_DATA;		break;
			case 'w': mode = I2C_SMBUS_WORD_DATA;		break;
			case 's': mode = I2C_SMBUS_BLOCK_DATA;		break;
			case 'i': mode = I2C_SMBUS_I2C_BLOCK_DATA;	break;
			default:
				bb_error_msg("invalid mode");
				bb_show_usage();
			}

			pec = argv[argc-1][1] == 'p';
			if (mode == I2C_SMBUS_BLOCK_DATA ||
					mode == I2C_SMBUS_I2C_BLOCK_DATA) {
				if (pec && mode == I2C_SMBUS_I2C_BLOCK_DATA)
					bb_error_msg_and_die(
						"PEC not supported for I2C "
						"block writes");
				if (opts & opt_m)
					bb_error_msg_and_die(
						"mask not supported for block "
						"writes");
			}
		}
	}

	/* Prepare the value(s) to be written according to current mode. */
	switch (mode) {
	case I2C_SMBUS_BYTE_DATA:
		val = xstrtou_range(argv[3], 0, 0, 0xff);
		break;
	case I2C_SMBUS_WORD_DATA:
		val = xstrtou_range(argv[3], 0, 0, 0xffff);
		break;
	case I2C_SMBUS_BLOCK_DATA:
	case I2C_SMBUS_I2C_BLOCK_DATA:
		for (blen = 3; blen < (argc - 1); blen++)
			block[blen] = xstrtou_range(argv[blen], 0, 0, 0xff);
		val = -1;
		break;
	default:
		val = -1;
		break;
	}

	if (opts & opt_m) {
		mask = xstrtou_range(opt_m_arg, 0, 0,
				(mode == I2C_SMBUS_BYTE ||
				 mode == I2C_SMBUS_BYTE_DATA) ? 0xff : 0xffff);
	}

	fd = i2c_dev_open(bus_num);
	check_write_funcs(fd, mode, pec);
	i2c_set_slave_addr(fd, bus_addr, opts & opt_f);

	if (!(opts & opt_y))
		confirm_action(bus_addr, mode, data_addr, pec);

	/*
	 * If we're using mask - read the current value here and adjust the
	 * value to be written.
	 */
	if (opts & opt_m) {
		int tmpval;

		switch (mode) {
		case I2C_SMBUS_BYTE:
			tmpval = i2c_smbus_read_byte(fd);
			break;
		case I2C_SMBUS_WORD_DATA:
			tmpval = i2c_smbus_read_word_data(fd, data_addr);
			break;
		default:
			tmpval = i2c_smbus_read_byte_data(fd, data_addr);
		}

		if (tmpval < 0)
			bb_perror_msg_and_die("can't read old value");

		val = (val & mask) | (tmpval & ~mask);

		if (!(opts & opt_y)) {
			bb_error_msg("old value 0x%0*x, write mask "
				"0x%0*x, will write 0x%0*x to register "
				"0x%02x",
				mode == I2C_SMBUS_WORD_DATA ? 4 : 2, tmpval,
				mode == I2C_SMBUS_WORD_DATA ? 4 : 2, mask,
				mode == I2C_SMBUS_WORD_DATA ? 4 : 2, val,
				data_addr);
			confirm_or_abort();
		}
	}

	if (pec)
		i2c_set_pec(fd, 1);

	switch (mode) {
	case I2C_SMBUS_BYTE:
		status = i2c_smbus_write_byte(fd, data_addr);
		break;
	case I2C_SMBUS_WORD_DATA:
		status = i2c_smbus_write_word_data(fd, data_addr, val);
		break;
	case I2C_SMBUS_BLOCK_DATA:
		status = i2c_smbus_write_block_data(fd, data_addr,
						    blen, block);
		break;
	case I2C_SMBUS_I2C_BLOCK_DATA:
		status = i2c_smbus_write_i2c_block_data(fd, data_addr,
							blen, block);
		break;
	default: /* I2C_SMBUS_BYTE_DATA */
		status = i2c_smbus_write_byte_data(fd, data_addr, val);
		break;
	}
	if (status < 0)
		bb_perror_msg_and_die("write failed");

	if (pec)
		i2c_set_pec(fd, 0); /* Clear PEC. */

	/* No readback required - we're done. */
	if (!(opts & opt_r))
		return 0;

	switch (mode) {
	case I2C_SMBUS_BYTE:
		status = i2c_smbus_read_byte(fd);
		val = data_addr;
		break;
	case I2C_SMBUS_WORD_DATA:
		status = i2c_smbus_read_word_data(fd, data_addr);
		break;
	default: /* I2C_SMBUS_BYTE_DATA */
		status = i2c_smbus_read_byte_data(fd, data_addr);
	}

	if (status < 0) {
		puts("Warning - readback failed");
	} else
	if (status != val) {
		printf("Warning - data mismatch - wrote "
		       "0x%0*x, read back 0x%0*x\n",
		       mode == I2C_SMBUS_WORD_DATA ? 4 : 2, val,
		       mode == I2C_SMBUS_WORD_DATA ? 4 : 2, status);
	} else {
		printf("Value 0x%0*x written, readback matched\n",
		       mode == I2C_SMBUS_WORD_DATA ? 4 : 2, val);
	}

	return 0;
}
Example #3
0
static int i2c_parse_data_addr(const char *data_addr)
{
	/* Data address must be an 8 bit integer. */
	return xstrtou_range(data_addr, 16, 0, 0xff);
}
Example #4
0
static int i2c_parse_bus_addr(const char *addr_str)
{
	/* Slave address must be in range 0x03 - 0x77. */
	return xstrtou_range(addr_str, 16, 0x03, 0x77);
}
Example #5
0
static int i2c_bus_lookup(const char *bus_str)
{
	return xstrtou_range(bus_str, 10, 0, 0xfffff);
}
Example #6
0
int run_parts_main(int argc, char **argv)
{
	const char *umask_p = "22";
	llist_t *arg_list = NULL;
	unsigned n;
	int ret;

#if ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS
	applet_long_options = runparts_longopts;
#endif
	/* We require exactly one argument: the directory name */
	opt_complementary = "=1:a::";
	getopt32(argv, "a:u:t"USE_FEATURE_RUN_PARTS_FANCY("l"), &arg_list, &umask_p);

	umask(xstrtou_range(umask_p, 8, 0, 07777));

	n = 1;
	while (arg_list && n < NUM_CMD) {
		cmd[n] = arg_list->data;
		arg_list = arg_list->link;
		n++;
	}
	/* cmd[n] = NULL; - is already zeroed out */

	/* run-parts has to sort executables by name before running them */

	recursive_action(argv[optind],
			ACTION_RECURSE|ACTION_FOLLOWLINKS,
			act,            /* file action */
			act,            /* dir action */
			NULL,           /* user data */
			1               /* depth */
		);

	if (!names)
		return 0;

	qsort(names, cur, sizeof(char *), bb_alphasort);

	n = 0;
	while (1) {
		char *name = *names++;
		if (!name)
			break;
		if (option_mask32 & (RUN_PARTS_OPT_t | RUN_PARTS_OPT_l)) {
			puts(name);
			continue;
		}
		cmd[0] = name;
		ret = wait4pid(spawn(cmd));
		if (ret == 0)
			continue;
		n = 1;
		if (ret < 0)
			bb_perror_msg("failed to exec %s", name);
		else /* ret > 0 */
			bb_error_msg("%s exited with return code %d", name, ret);
	}

	return n;
}