Home | History | Annotate | Download | only in updater
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 /* Useful direct commands to the EC host interface */
     17 
     18 #define LOG_TAG "fwtool"
     19 
     20 #include <errno.h>
     21 #include <stdint.h>
     22 #include <stdlib.h>
     23 #include <string.h>
     24 #include <unistd.h>
     25 
     26 #include "ec_commands.h"
     27 #include "debug_cmd.h"
     28 #include "flash_device.h"
     29 #include "update_log.h"
     30 
     31 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
     32 
     33 static void *ec;
     34 
     35 static void *get_ec(void)
     36 {
     37 	if (!ec)
     38 		ec = flash_open("ec", NULL);
     39 
     40 	return ec;
     41 }
     42 
     43 static int ec_readmem(int offset, int bytes, void *dest)
     44 {
     45 	struct ec_params_read_memmap r_mem;
     46 	int r;
     47 
     48 	r_mem.offset = offset;
     49 	r_mem.size = bytes;
     50 	return flash_cmd(ec, EC_CMD_READ_MEMMAP, 0,
     51 			 &r_mem, sizeof(r_mem), dest, bytes);
     52 }
     53 
     54 static uint8_t ec_readmem8(int offset)
     55 {
     56 	uint8_t val;
     57 	int ret;
     58 	ret = ec_readmem(offset, sizeof(val), &val);
     59 	return ret ? 0 : val;
     60 }
     61 
     62 static uint32_t ec_readmem32(int offset)
     63 {
     64 	uint32_t val;
     65 	int ret;
     66 	ret = ec_readmem(offset, sizeof(val), &val);
     67 	return ret ? 0 : val;
     68 }
     69 
     70 static int cmd_ec_battery(int argc, const char **argv)
     71 {
     72 	char batt_text[EC_MEMMAP_TEXT_MAX + 1];
     73 	uint32_t val;
     74 
     75 	if (!get_ec())
     76 		return -ENODEV;
     77 
     78 	printf("Battery info:\n");
     79 
     80 	val = ec_readmem8(EC_MEMMAP_BATTERY_VERSION);
     81 	if (val < 1) {
     82 		fprintf(stderr, "Battery version %d is not supported\n", val);
     83 		return -EINVAL;
     84 	}
     85 
     86 	memset(batt_text, 0, EC_MEMMAP_TEXT_MAX + 1);
     87 	ec_readmem(EC_MEMMAP_BATT_MFGR, sizeof(batt_text), batt_text);
     88 	printf("  OEM name:               %s\n", batt_text);
     89 	ec_readmem(EC_MEMMAP_BATT_MODEL, sizeof(batt_text), batt_text);
     90 	printf("  Model number:           %s\n", batt_text);
     91 	printf("  Chemistry   :           %s\n", batt_text);
     92 	ec_readmem(EC_MEMMAP_BATT_SERIAL, sizeof(batt_text), batt_text);
     93 	printf("  Serial number:          %s\n", batt_text);
     94 	val = ec_readmem32(EC_MEMMAP_BATT_DCAP);
     95 	printf("  Design capacity:        %u mAh\n", val);
     96 	val = ec_readmem32(EC_MEMMAP_BATT_LFCC);
     97 	printf("  Last full charge:       %u mAh\n", val);
     98 	val = ec_readmem32(EC_MEMMAP_BATT_DVLT);
     99 	printf("  Design output voltage   %u mV\n", val);
    100 	val = ec_readmem32(EC_MEMMAP_BATT_CCNT);
    101 	printf("  Cycle count             %u\n", val);
    102 	val = ec_readmem32(EC_MEMMAP_BATT_VOLT);
    103 	printf("  Present voltage         %u mV\n", val);
    104 	val = ec_readmem32(EC_MEMMAP_BATT_RATE);
    105 	printf("  Present current         %u mA\n", val);
    106 	val = ec_readmem32(EC_MEMMAP_BATT_CAP);
    107 	printf("  Remaining capacity      %u mAh\n", val);
    108 	val = ec_readmem8(EC_MEMMAP_BATT_FLAG);
    109 	printf("  Flags                   0x%02x", val);
    110 	if (val & EC_BATT_FLAG_AC_PRESENT)
    111 		printf(" AC_PRESENT");
    112 	if (val & EC_BATT_FLAG_BATT_PRESENT)
    113 		printf(" BATT_PRESENT");
    114 	if (val & EC_BATT_FLAG_DISCHARGING)
    115 		printf(" DISCHARGING");
    116 	if (val & EC_BATT_FLAG_CHARGING)
    117 		printf(" CHARGING");
    118 	if (val & EC_BATT_FLAG_LEVEL_CRITICAL)
    119 		printf(" LEVEL_CRITICAL");
    120 	printf("\n");
    121 
    122 	return 0;
    123 }
    124 
    125 /* BQ25892 I2C registers */
    126 #define BQ2589X_ADDR         (0x6B << 1)
    127 #define BQ2589X_REG_CFG1            0x02
    128 #define BQ2589X_CFG1_CONV_START     (1<<7)
    129 #define BQ2589X_REG_ADC_BATT_VOLT   0x0E
    130 #define BQ2589X_REG_ADC_SYS_VOLT    0x0F
    131 #define BQ2589X_REG_ADC_TS          0x10
    132 #define BQ2589X_REG_ADC_VBUS_VOLT   0x11
    133 #define BQ2589X_REG_ADC_CHG_CURR    0x12
    134 #define BQ2589X_REG_ADC_INPUT_CURR  0x13
    135 
    136 static int bq25892_read(int reg, int *value)
    137 {
    138 	int rv;
    139 	struct ec_response_i2c_read r;
    140 	struct ec_params_i2c_read p = {
    141 		.port = 0, .read_size = 8, .addr = BQ2589X_ADDR, .offset = reg
    142 	};
    143 
    144 	rv = flash_cmd(ec, EC_CMD_I2C_READ, 0, &p, sizeof(p), &r, sizeof(r));
    145 	if (rv < 0) {
    146 		*value = -1;
    147 		return rv;
    148 	}
    149 
    150 	*value = r.data;
    151 	return 0;
    152 }
    153 
    154 static int bq25892_write(int reg, int value)
    155 {
    156 	int rv;
    157 	struct ec_params_i2c_write p = {
    158 		.port = 0, .write_size = 8, .addr = BQ2589X_ADDR,
    159 		.offset = reg, .data = value
    160 	};
    161 
    162 	rv = flash_cmd(ec, EC_CMD_I2C_WRITE, 0, &p, sizeof(p), NULL, 0);
    163 	return rv < 0 ? rv : 0;
    164 }
    165 
    166 static int cmd_ec_bq25892(int argc, const char **argv)
    167 {
    168 	int i;
    169 	int value;
    170 	int rv;
    171 	int batt_mv, sys_mv, vbus_mv, chg_ma, input_ma;
    172 
    173 
    174 	if (!get_ec())
    175 		return -ENODEV;
    176 
    177 	/* Trigger one ADC conversion */
    178 	bq25892_read(BQ2589X_REG_CFG1, &value);
    179 	bq25892_write(BQ2589X_REG_CFG1, value | BQ2589X_CFG1_CONV_START);
    180 	do {
    181 		rv = bq25892_read(BQ2589X_REG_CFG1, &value);
    182 	} while ((value & BQ2589X_CFG1_CONV_START) || (rv < 0));
    183 
    184 	bq25892_read(BQ2589X_REG_ADC_BATT_VOLT, &batt_mv);
    185 	bq25892_read(BQ2589X_REG_ADC_SYS_VOLT, &sys_mv);
    186 	bq25892_read(BQ2589X_REG_ADC_VBUS_VOLT, &vbus_mv);
    187 	bq25892_read(BQ2589X_REG_ADC_CHG_CURR, &chg_ma);
    188 	bq25892_read(BQ2589X_REG_ADC_INPUT_CURR, &input_ma);
    189 	printf("ADC Batt %dmV Sys %dmV VBUS %dmV Chg %dmA Input %dmA\n",
    190 		2304 + (batt_mv & 0x7f) * 20, 2304 + sys_mv * 20,
    191 		2600 + (vbus_mv & 0x7f) * 100,
    192 		chg_ma * 50, 100 + (input_ma & 0x3f) * 50);
    193 
    194 	printf("REG:");
    195 	for (i = 0; i <= 0x14; ++i)
    196 		printf(" %02x", i);
    197 	printf("\n");
    198 
    199 	printf("VAL:");
    200 	for (i = 0; i <= 0x14; ++i) {
    201 		rv = bq25892_read(i, &value);
    202 		if (rv)
    203 			return rv;
    204 		printf(" %02x", value);
    205 	}
    206 	printf("\n");
    207 	return 0;
    208 }
    209 
    210 /* BQ27742 I2C registers */
    211 #define BQ27742_ADDR         	    0xAA
    212 #define BQ27742_REG_CTRL            0x00
    213 #define BQ27742_REG_FLAGS           0x0A
    214 #define BQ27742_REG_CHARGING_MV     0x30
    215 #define BQ27742_REG_CHARGING_MA     0x32
    216 #define BQ27742_REG_PROTECTOR       0x6D
    217 
    218 static int bq27742_read(int reg, int size, int *value)
    219 {
    220 	int rv;
    221 	struct ec_response_i2c_read r;
    222 	struct ec_params_i2c_read p = {
    223 		.port = 0, .read_size = size, .addr = BQ27742_ADDR,
    224 		.offset = reg
    225 	};
    226 
    227 	rv = flash_cmd(ec, EC_CMD_I2C_READ, 0, &p, sizeof(p), &r, sizeof(r));
    228 	if (rv < 0) {
    229 		*value = -1;
    230 		return rv;
    231 	}
    232 
    233 	*value = r.data;
    234 	return 0;
    235 }
    236 
    237 static int bq27742_write(int reg, int size, int value)
    238 {
    239 	int rv;
    240 	struct ec_params_i2c_write p = {
    241 		.port = 0, .write_size = size, .addr = BQ27742_ADDR,
    242 		.offset = reg, .data = value
    243 	};
    244 
    245 	rv = flash_cmd(ec, EC_CMD_I2C_WRITE, 0, &p, sizeof(p), NULL, 0);
    246 	return rv < 0 ? rv : 0;
    247 }
    248 
    249 static int cmd_ec_bq27742(int argc, const char **argv)
    250 {
    251 	int i;
    252 	int value;
    253 	int rv;
    254 	int chg_mv, chg_ma;
    255 
    256 
    257 	if (!get_ec())
    258 		return -ENODEV;
    259 
    260 	/* Get chip ID in Control subcommand DEVICE_TYPE (0x1) */
    261 	bq27742_write(BQ27742_REG_CTRL, 16, 0x1);
    262 	bq27742_read(BQ27742_REG_CTRL, 16, &value);
    263 	printf("ID: BQ27%3x\n", value);
    264 
    265 	bq27742_read(BQ27742_REG_CHARGING_MV, 16, &chg_mv);
    266 	bq27742_read(BQ27742_REG_CHARGING_MA, 16, &chg_ma);
    267 	printf("Requested charge: %d mV %d mA\n", chg_mv, chg_ma);
    268 
    269 	bq27742_read(BQ27742_REG_FLAGS, 16, &value);
    270 	printf("Flags: %04x\n", value);
    271 	bq27742_read(BQ27742_REG_PROTECTOR, 8, &value);
    272 	printf("ProtectorState: %02x\n", value);
    273 
    274 	return 0;
    275 }
    276 
    277 static int cmd_ec_chargecontrol(int argc, const char **argv)
    278 {
    279 	struct ec_params_charge_control p;
    280 	int rv;
    281 
    282 	if (argc != 2) {
    283 		fprintf(stderr, "Usage: %s <normal | idle | discharge>\n",
    284 			argv[0]);
    285 		return -EINVAL;
    286 	}
    287 
    288 	if (!strcasecmp(argv[1], "normal")) {
    289 		p.mode = CHARGE_CONTROL_NORMAL;
    290 	} else if (!strcasecmp(argv[1], "idle")) {
    291 		p.mode = CHARGE_CONTROL_IDLE;
    292 	} else if (!strcasecmp(argv[1], "discharge")) {
    293 		p.mode = CHARGE_CONTROL_DISCHARGE;
    294 	} else {
    295 		fprintf(stderr, "Bad value.\n");
    296 		return -EINVAL;
    297 	}
    298 
    299 	if (!get_ec())
    300 		return -ENODEV;
    301 
    302 	rv = flash_cmd(ec, EC_CMD_CHARGE_CONTROL, 1, &p, sizeof(p), NULL, 0);
    303 	if (rv < 0) {
    304 		fprintf(stderr, "Is AC connected?\n");
    305 		return rv;
    306 	}
    307 
    308 	switch (p.mode) {
    309 	case CHARGE_CONTROL_NORMAL:
    310 		printf("Charge state machine normal mode.\n");
    311 		break;
    312 	case CHARGE_CONTROL_IDLE:
    313 		printf("Charge state machine force idle.\n");
    314 		break;
    315 	case CHARGE_CONTROL_DISCHARGE:
    316 		printf("Charge state machine force discharge.\n");
    317 		break;
    318 	default:
    319 		break;
    320 	}
    321 	return 0;
    322 }
    323 
    324 static int cmd_ec_console(int argc, const char **argv)
    325 {
    326 	char data[128];
    327 	int rv;
    328 
    329 	if (!get_ec())
    330 		return -ENODEV;
    331 
    332 	/* Snapshot the EC console */
    333 	rv = flash_cmd(ec, EC_CMD_CONSOLE_SNAPSHOT, 0, NULL, 0, NULL, 0);
    334 	if (rv < 0)
    335 		return rv;
    336 
    337 	/* Loop and read from the snapshot until it's done */
    338 	while (1) {
    339 		memset(data, 0, sizeof(data));
    340 		rv = flash_cmd(ec, EC_CMD_CONSOLE_READ, 0,
    341 			       NULL, 0, data, sizeof(data));
    342 		if (rv)
    343 			return rv;
    344 
    345 		/* Empty response means done */
    346 		if (!data[0])
    347 			break;
    348 
    349 		/* Make sure output is null-terminated, then dump it */
    350 		data[sizeof(data) - 1] = '\0';
    351 		fputs(data, stdout);
    352 	}
    353 	printf("\n");
    354 	return 0;
    355 }
    356 
    357 static int cmd_ec_gpioget(int argc, const char **argv)
    358 {
    359 	struct ec_params_gpio_get_v1 p_v1;
    360 	struct ec_response_gpio_get_v1 r_v1;
    361 	int i, rv, subcmd, num_gpios;
    362 
    363 	if (!get_ec())
    364 		return -ENODEV;
    365 
    366 	if (argc > 2) {
    367 		printf("Usage: %s [<subcmd> <GPIO name>]\n", argv[0]);
    368 		printf("'gpioget <GPIO_NAME>' - Get value by name\n");
    369 		printf("'gpioget count' - Get count of GPIOS\n");
    370 		printf("'gpioget all' - Get info for all GPIOs\n");
    371 		return -1;
    372 	}
    373 
    374 	/* Keeping it consistent with console command behavior */
    375 	if (argc == 1)
    376 		subcmd = EC_GPIO_GET_INFO;
    377 	else if (!strcmp(argv[1], "count"))
    378 		subcmd = EC_GPIO_GET_COUNT;
    379 	else if (!strcmp(argv[1], "all"))
    380 		subcmd = EC_GPIO_GET_INFO;
    381 	else
    382 		subcmd = EC_GPIO_GET_BY_NAME;
    383 
    384 	if (subcmd == EC_GPIO_GET_BY_NAME) {
    385 		p_v1.subcmd = EC_GPIO_GET_BY_NAME;
    386 		if (strlen(argv[1]) + 1 > sizeof(p_v1.get_value_by_name.name)) {
    387 			fprintf(stderr, "GPIO name too long.\n");
    388 			return -1;
    389 		}
    390 		strcpy(p_v1.get_value_by_name.name, argv[1]);
    391 
    392 		rv = flash_cmd(ec, EC_CMD_GPIO_GET, 1, &p_v1,
    393 				sizeof(p_v1), &r_v1, sizeof(r_v1));
    394 
    395 		if (rv < 0)
    396 			return rv;
    397 
    398 		printf("GPIO %s = %d\n", p_v1.get_value_by_name.name,
    399 			r_v1.get_value_by_name.val);
    400 		return 0;
    401 	}
    402 
    403 	/* Need GPIO count for EC_GPIO_GET_COUNT or EC_GPIO_GET_INFO */
    404 	p_v1.subcmd = EC_GPIO_GET_COUNT;
    405 	rv = flash_cmd(ec, EC_CMD_GPIO_GET, 1, &p_v1,
    406 			sizeof(p_v1), &r_v1, sizeof(r_v1));
    407 	if (rv < 0)
    408 		return rv;
    409 
    410 	if (subcmd == EC_GPIO_GET_COUNT) {
    411 		printf("GPIO COUNT = %d\n", r_v1.get_count.val);
    412 		return 0;
    413 	}
    414 
    415 	/* subcmd EC_GPIO_GET_INFO */
    416 	num_gpios = r_v1.get_count.val;
    417 	p_v1.subcmd = EC_GPIO_GET_INFO;
    418 
    419 	for (i = 0; i < num_gpios; i++) {
    420 		p_v1.get_info.index = i;
    421 
    422 		rv = flash_cmd(ec, EC_CMD_GPIO_GET, 1, &p_v1,
    423 				sizeof(p_v1), &r_v1, sizeof(r_v1));
    424 		if (rv < 0)
    425 			return rv;
    426 
    427 		printf("%2d %-32s 0x%04X\n", r_v1.get_info.val,
    428 			r_v1.get_info.name, r_v1.get_info.flags);
    429 	}
    430 
    431 	return 0;
    432 }
    433 
    434 
    435 static int cmd_ec_gpioset(int argc, const char **argv)
    436 {
    437 	struct ec_params_gpio_set p;
    438 	char *e;
    439 	int rv;
    440 
    441 	if (!get_ec())
    442 		return -ENODEV;
    443 
    444 	if (argc != 3) {
    445 		fprintf(stderr, "Usage: %s <GPIO name> <0 | 1>\n", argv[0]);
    446 		return -1;
    447 	}
    448 
    449 	if (strlen(argv[1]) + 1 > sizeof(p.name)) {
    450 		fprintf(stderr, "GPIO name too long.\n");
    451 		return -1;
    452 	}
    453 	strcpy(p.name, argv[1]);
    454 
    455 	p.val = strtol(argv[2], &e, 0);
    456 	if (e && *e) {
    457 		fprintf(stderr, "Bad value.\n");
    458 		return -1;
    459 	}
    460 
    461 	rv = flash_cmd(ec, EC_CMD_GPIO_SET, 0, &p, sizeof(p), NULL, 0);
    462 	if (rv < 0)
    463 		return rv;
    464 
    465 	printf("GPIO %s set to %d\n", p.name, p.val);
    466 	return 0;
    467 }
    468 
    469 static int ec_hash_print(const struct ec_response_vboot_hash *r)
    470 {
    471 	int i;
    472 
    473 	if (r->status == EC_VBOOT_HASH_STATUS_BUSY) {
    474 		printf("status:  busy\n");
    475 		return 0;
    476 	} else if (r->status == EC_VBOOT_HASH_STATUS_NONE) {
    477 		printf("status:  unavailable\n");
    478 		return 0;
    479 	} else if (r->status != EC_VBOOT_HASH_STATUS_DONE) {
    480 		printf("status:  %d\n", r->status);
    481 		return 0;
    482 	}
    483 
    484 	printf("status:  done\n");
    485 	if (r->hash_type == EC_VBOOT_HASH_TYPE_SHA256)
    486 		printf("type:    SHA-256\n");
    487 	else
    488 		printf("type:    %d\n", r->hash_type);
    489 
    490 	printf("offset:  0x%08x\n", r->offset);
    491 	printf("size:    0x%08x\n", r->size);
    492 
    493 	printf("hash:    ");
    494 	for (i = 0; i < r->digest_size; i++)
    495 		printf("%02x", r->hash_digest[i]);
    496 	printf("\n");
    497 	return 0;
    498 }
    499 
    500 static int cmd_ec_echash(int argc, const char **argv)
    501 {
    502 	struct ec_params_vboot_hash p;
    503 	struct ec_response_vboot_hash r;
    504 	char *e;
    505 	int rv;
    506 
    507 	if (!get_ec())
    508 		return -ENODEV;
    509 
    510 	if (argc < 2) {
    511 		/* Get hash status */
    512 		p.cmd = EC_VBOOT_HASH_GET;
    513 		rv = flash_cmd(ec, EC_CMD_VBOOT_HASH, 0,
    514 				&p, sizeof(p), &r, sizeof(r));
    515 		if (rv < 0)
    516 			return rv;
    517 
    518 		return ec_hash_print(&r);
    519 	}
    520 
    521 	if (argc == 2 && !strcasecmp(argv[1], "abort")) {
    522 		/* Abort hash calculation */
    523 		p.cmd = EC_VBOOT_HASH_ABORT;
    524 		rv = flash_cmd(ec, EC_CMD_VBOOT_HASH, 0,
    525 				&p, sizeof(p), &r, sizeof(r));
    526 		return (rv < 0 ? rv : 0);
    527 	}
    528 
    529 	/* The only other commands are start and recalc */
    530 	if (!strcasecmp(argv[1], "start"))
    531 		p.cmd = EC_VBOOT_HASH_START;
    532 	else if (!strcasecmp(argv[1], "recalc"))
    533 		p.cmd = EC_VBOOT_HASH_RECALC;
    534 	else
    535 		return -EINVAL;
    536 
    537 	p.hash_type = EC_VBOOT_HASH_TYPE_SHA256;
    538 
    539 	if (argc < 3) {
    540 		fprintf(stderr, "Must specify offset\n");
    541 		return -1;
    542 	}
    543 
    544 	if (!strcasecmp(argv[2], "ro")) {
    545 		p.offset = EC_VBOOT_HASH_OFFSET_RO;
    546 		p.size = 0;
    547 		printf("Hashing EC-RO...\n");
    548 	} else if (!strcasecmp(argv[2], "rw")) {
    549 		p.offset = EC_VBOOT_HASH_OFFSET_RW;
    550 		p.size = 0;
    551 		printf("Hashing EC-RW...\n");
    552 	} else if (argc < 4) {
    553 		fprintf(stderr, "Must specify size\n");
    554 		return -1;
    555 	} else {
    556 		p.offset = strtol(argv[2], &e, 0);
    557 		if (e && *e) {
    558 			fprintf(stderr, "Bad offset.\n");
    559 			return -1;
    560 		}
    561 		p.size = strtol(argv[3], &e, 0);
    562 		if (e && *e) {
    563 			fprintf(stderr, "Bad size.\n");
    564 			return -1;
    565 		}
    566 		printf("Hashing %d bytes at offset %d...\n", p.size, p.offset);
    567 	}
    568 
    569 	if (argc == 5) {
    570 		/*
    571 		 * Technically nonce can be any binary data up to 64 bytes,
    572 		 * but this command only supports a 32-bit value.
    573 		 */
    574 		uint32_t nonce = strtol(argv[4], &e, 0);
    575 		if (e && *e) {
    576 			fprintf(stderr, "Bad nonce integer.\n");
    577 			return -1;
    578 		}
    579 		memcpy(p.nonce_data, &nonce, sizeof(nonce));
    580 		p.nonce_size = sizeof(nonce);
    581 	} else
    582 		p.nonce_size = 0;
    583 
    584 	rv = flash_cmd(ec, EC_CMD_VBOOT_HASH, 0, &p, sizeof(p), &r, sizeof(r));
    585 	if (rv < 0)
    586 		return rv;
    587 
    588 	/* Start command doesn't wait for hashing to finish */
    589 	if (p.cmd == EC_VBOOT_HASH_START)
    590 		return 0;
    591 
    592 	/* Recalc command does wait around, so a result is ready now */
    593 	return ec_hash_print(&r);
    594 }
    595 
    596 #define LIGHTBAR_NUM_SEQUENCES 13
    597 
    598 static int lb_do_cmd(enum lightbar_command cmd,
    599 		     struct ec_params_lightbar *in,
    600 		     struct ec_response_lightbar *out)
    601 {
    602 	int rv;
    603 	in->cmd = cmd;
    604 	rv = flash_cmd(ec, EC_CMD_LIGHTBAR_CMD, 0,
    605 			in, 120,
    606 			out, 120);
    607 	return (rv < 0 ? rv : 0);
    608 }
    609 
    610 static int cmd_ec_lightbar(int argc, const char **argv)
    611 {
    612 	unsigned i;
    613 	int r;
    614 	struct ec_params_lightbar param;
    615 	struct ec_response_lightbar resp;
    616 
    617 	if (!get_ec())
    618 		return -ENODEV;
    619 
    620 	if (1 == argc) {		/* no args = dump 'em all */
    621 		r = lb_do_cmd(LIGHTBAR_CMD_DUMP, &param, &resp);
    622 		if (r)
    623 			return r;
    624 		for (i = 0; i < ARRAY_SIZE(resp.dump.vals); i++) {
    625 			printf(" %02x     %02x     %02x\n",
    626 			       resp.dump.vals[i].reg,
    627 			       resp.dump.vals[i].ic0,
    628 			       resp.dump.vals[i].ic1);
    629 		}
    630 		return 0;
    631 	}
    632 
    633 	if (argc == 2 && !strcasecmp(argv[1], "init"))
    634 		return lb_do_cmd(LIGHTBAR_CMD_INIT, &param, &resp);
    635 
    636 	if (argc == 2 && !strcasecmp(argv[1], "off"))
    637 		return lb_do_cmd(LIGHTBAR_CMD_OFF, &param, &resp);
    638 
    639 	if (argc == 2 && !strcasecmp(argv[1], "on"))
    640 		return lb_do_cmd(LIGHTBAR_CMD_ON, &param, &resp);
    641 
    642 	if (!strcasecmp(argv[1], "version")) {
    643 		r = lb_do_cmd(LIGHTBAR_CMD_VERSION, &param, &resp);
    644 		if (!r)
    645 			printf("version %d flags 0x%x\n",
    646 			       resp.version.num, resp.version.flags);
    647 		return r;
    648 	}
    649 
    650 	if (argc > 1 && !strcasecmp(argv[1], "brightness")) {
    651 		char *e;
    652 		int rv;
    653 		if (argc > 2) {
    654 			param.set_brightness.num = 0xff &
    655 				strtoul(argv[2], &e, 16);
    656 			return lb_do_cmd(LIGHTBAR_CMD_SET_BRIGHTNESS,
    657 					 &param, &resp);
    658 		}
    659 		rv = lb_do_cmd(LIGHTBAR_CMD_GET_BRIGHTNESS,
    660 			       &param, &resp);
    661 		if (rv)
    662 			return rv;
    663 		printf("%02x\n", resp.get_brightness.num);
    664 		return 0;
    665 	}
    666 
    667 	if (argc > 1 && !strcasecmp(argv[1], "demo")) {
    668 		int rv;
    669 		if (argc > 2) {
    670 			if (!strcasecmp(argv[2], "on") || argv[2][0] == '1')
    671 				param.demo.num = 1;
    672 			else if (!strcasecmp(argv[2], "off") ||
    673 				 argv[2][0] == '0')
    674 				param.demo.num = 0;
    675 			else {
    676 				fprintf(stderr, "Invalid arg\n");
    677 				return -1;
    678 			}
    679 			return lb_do_cmd(LIGHTBAR_CMD_DEMO, &param, &resp);
    680 		}
    681 
    682 		rv = lb_do_cmd(LIGHTBAR_CMD_GET_DEMO, &param, &resp);
    683 		if (rv)
    684 			return rv;
    685 		printf("%s\n", resp.get_demo.num ? "on" : "off");
    686 		return 0;
    687 	}
    688 
    689 	if (argc > 2 && !strcasecmp(argv[1], "seq")) {
    690 		char *e;
    691 		uint8_t num;
    692 		num = 0xff & strtoul(argv[2], &e, 16);
    693 		if (e && *e) {
    694 			if (!strcasecmp(argv[2], "stop"))
    695 				num = 0x8;
    696 			else if (!strcasecmp(argv[2], "run"))
    697 				num = 0x9;
    698 			else if (!strcasecmp(argv[2], "konami"))
    699 				num = 0xA;
    700 			else
    701 				num = LIGHTBAR_NUM_SEQUENCES;
    702 		}
    703 		if (num >= LIGHTBAR_NUM_SEQUENCES) {
    704 			fprintf(stderr, "Invalid arg\n");
    705 			return -1;
    706 		}
    707 		param.seq.num = num;
    708 		return lb_do_cmd(LIGHTBAR_CMD_SEQ, &param, &resp);
    709 	}
    710 
    711 	if (argc == 4) {
    712 		char *e;
    713 		param.reg.ctrl = 0xff & strtoul(argv[1], &e, 16);
    714 		param.reg.reg = 0xff & strtoul(argv[2], &e, 16);
    715 		param.reg.value = 0xff & strtoul(argv[3], &e, 16);
    716 		return lb_do_cmd(LIGHTBAR_CMD_REG, &param, &resp);
    717 	}
    718 
    719 	if (argc == 5) {
    720 		char *e;
    721 		param.set_rgb.led = strtoul(argv[1], &e, 16);
    722 		param.set_rgb.red = strtoul(argv[2], &e, 16);
    723 		param.set_rgb.green = strtoul(argv[3], &e, 16);
    724 		param.set_rgb.blue = strtoul(argv[4], &e, 16);
    725 		return lb_do_cmd(LIGHTBAR_CMD_SET_RGB, &param, &resp);
    726 	}
    727 
    728 	/* Only thing left is to try to read an LED value */
    729 	if (argc == 2) {
    730 		char *e;
    731 		param.get_rgb.led = strtoul(argv[1], &e, 0);
    732 		if (!(e && *e)) {
    733 			r = lb_do_cmd(LIGHTBAR_CMD_GET_RGB, &param, &resp);
    734 			if (r)
    735 				return r;
    736 			printf("%02x %02x %02x\n",
    737 			       resp.get_rgb.red,
    738 			       resp.get_rgb.green,
    739 			       resp.get_rgb.blue);
    740 			return 0;
    741 		}
    742 	}
    743 
    744 	return 0;
    745 }
    746 
    747 /* PI3USB9281 I2C registers */
    748 #define PI3USB9281_ADDR      (0x25 << 1)
    749 #define PI3USB9281_REG_DEV_ID       0x01
    750 #define PI3USB9281_REG_CONTROL      0x02
    751 #define PI3USB9281_REG_INT          0x03
    752 #define PI3USB9281_REG_INT_MASK     0x05
    753 #define PI3USB9281_REG_DEV_TYPE     0x0a
    754 #define PI3USB9281_REG_CHG_STATUS   0x0e
    755 #define PI3USB9281_REG_MANUAL       0x13
    756 #define PI3USB9281_REG_RESET        0x1b
    757 #define PI3USB9281_REG_VBUS         0x1d
    758 
    759 static const uint8_t pi3usb9281_regs[] = {
    760 	PI3USB9281_REG_DEV_ID, PI3USB9281_REG_CONTROL, PI3USB9281_REG_INT,
    761 	PI3USB9281_REG_INT_MASK, PI3USB9281_REG_DEV_TYPE, PI3USB9281_REG_CHG_STATUS,
    762 	PI3USB9281_REG_MANUAL, PI3USB9281_REG_VBUS
    763 };
    764 #define PI3USB9281_COUNT ARRAY_SIZE(pi3usb9281_regs)
    765 
    766 static int pi3usb9281_read(int reg, int *value)
    767 {
    768 	int rv;
    769 	struct ec_response_i2c_read r;
    770 	struct ec_params_i2c_read p = {
    771 		.port = 0, .read_size = 8, .addr = PI3USB9281_ADDR, .offset = reg
    772 	};
    773 
    774 	rv = flash_cmd(ec, EC_CMD_I2C_READ, 0, &p, sizeof(p), &r, sizeof(r));
    775 	if (rv < 0) {
    776 		*value = -1;
    777 		return rv;
    778 	}
    779 
    780 	*value = r.data;
    781 	return 0;
    782 }
    783 
    784 static int cmd_ec_pi3usb9281(int argc, const char **argv)
    785 {
    786 	unsigned i;
    787 	int value;
    788 	int rv;
    789 	int dev_type, chg_stat, vbus;
    790 	char *apple_chg = "", *proprio_chg = "";
    791 
    792 	if (!get_ec())
    793 		return -ENODEV;
    794 
    795 	pi3usb9281_read(PI3USB9281_REG_DEV_TYPE, &dev_type);
    796 	pi3usb9281_read(PI3USB9281_REG_CHG_STATUS, &chg_stat);
    797 	pi3usb9281_read(PI3USB9281_REG_VBUS, &vbus);
    798 	switch((chg_stat>>2)&7) {
    799 	case 4: apple_chg = "Apple 2.4A"; break;
    800 	case 2: apple_chg = "Apple 2A"; break;
    801 	case 1: apple_chg = "Apple 1A"; break;
    802 	}
    803 	switch(chg_stat&3) {
    804 	case 3: proprio_chg = "type-2"; break;
    805 	case 2: proprio_chg = "type-1"; break;
    806 	case 1: proprio_chg = "rsvd"; break;
    807 	}
    808 	printf("USB: %s%s%s%s%s%s Charger: %s%s VBUS: %d\n",
    809 		dev_type & (1<<6) ? "DCP" : " ",
    810 		dev_type & (1<<5) ? "CDP" : " ",
    811 		dev_type & (1<<4) ? "CarKit" : " ",
    812 		dev_type & (1<<2) ? "SDP" : " ",
    813 		dev_type & (1<<1) ? "OTG" : " ",
    814 		dev_type & (1<<0) ? "MHL" : " ",
    815 		apple_chg,
    816 		proprio_chg,
    817 		!!(vbus & 2));
    818 
    819 	printf("REG:");
    820 	for (i = 0; i < PI3USB9281_COUNT; ++i)
    821 		printf(" %02x", pi3usb9281_regs[i]);
    822 	printf("\n");
    823 
    824 	printf("VAL:");
    825 	for (i = 0; i < PI3USB9281_COUNT; ++i) {
    826 		rv = pi3usb9281_read(pi3usb9281_regs[i], &value);
    827 		if (rv)
    828 			return rv;
    829 		printf(" %02x", value);
    830 	}
    831 	printf("\n");
    832 	return 0;
    833 }
    834 
    835 #define PD_ROLE_SINK   0
    836 #define PD_ROLE_SOURCE 1
    837 #define PD_ROLE_UFP    0
    838 #define PD_ROLE_DFP    1
    839 
    840 static int cmd_ec_usbpd(int argc, const char **argv)
    841 {
    842 	const char *role_str[] = {"", "toggle", "toggle-off", "sink", "source"};
    843 	const char *mux_str[] = {"", "none", "usb", "dp", "dock", "auto"};
    844 	const char *swap_str[] = {"", "dr_swap", "pr_swap", "vconn_swap"};
    845 	struct ec_params_usb_pd_control p;
    846 	struct ec_response_usb_pd_control_v1 r;
    847 	int rv, i;
    848         unsigned j;
    849 	int option_ok;
    850 	char *e;
    851 
    852 	if (!get_ec())
    853 		return -ENODEV;
    854 
    855 	p.role = USB_PD_CTRL_ROLE_NO_CHANGE;
    856 	p.mux = USB_PD_CTRL_MUX_NO_CHANGE;
    857 	p.swap = USB_PD_CTRL_SWAP_NONE;
    858 
    859 	if (argc < 2) {
    860 		fprintf(stderr, "No port specified.\n");
    861 		return -1;
    862 	}
    863 
    864 	p.port = strtol(argv[1], &e, 0);
    865 	if (e && *e) {
    866 		fprintf(stderr, "Invalid param (port)\n");
    867 		return -1;
    868 	}
    869 
    870 	for (i = 2; i < argc; ++i) {
    871 		option_ok = 0;
    872 		if (!strcmp(argv[i], "auto")) {
    873 			if (argc != 3) {
    874 				fprintf(stderr, "\"auto\" may not be used "
    875 						"with other options.\n");
    876 				return -1;
    877 			}
    878 			p.role = USB_PD_CTRL_ROLE_TOGGLE_ON;
    879 			p.mux = USB_PD_CTRL_MUX_AUTO;
    880 			continue;
    881 		}
    882 
    883 		for (j = 0; j < ARRAY_SIZE(role_str); ++j) {
    884 			if (!strcmp(argv[i], role_str[j])) {
    885 				if (p.role != USB_PD_CTRL_ROLE_NO_CHANGE) {
    886 					fprintf(stderr,
    887 						"Only one role allowed.\n");
    888 					return -1;
    889 				}
    890 				p.role = j;
    891 				option_ok = 1;
    892 				break;
    893 			}
    894 		}
    895 		if (option_ok)
    896 			continue;
    897 
    898 		for (j = 0; j < ARRAY_SIZE(mux_str); ++j) {
    899 			if (!strcmp(argv[i], mux_str[j])) {
    900 				if (p.mux != USB_PD_CTRL_MUX_NO_CHANGE) {
    901 					fprintf(stderr,
    902 						"Only one mux type allowed.\n");
    903 					return -1;
    904 				}
    905 				p.mux = j;
    906 				option_ok = 1;
    907 				break;
    908 			}
    909 		}
    910 		if (option_ok)
    911 			continue;
    912 
    913 		for (j = 0; j < ARRAY_SIZE(swap_str); ++j) {
    914 			if (!strcmp(argv[i], swap_str[j])) {
    915 				if (p.swap != USB_PD_CTRL_SWAP_NONE) {
    916 					fprintf(stderr,
    917 						"Only one swap type allowed.\n");
    918 					return -1;
    919 				}
    920 				p.swap = j;
    921 				option_ok = 1;
    922 				break;
    923 			}
    924 		}
    925 
    926 
    927 		if (!option_ok) {
    928 			fprintf(stderr, "Unknown option: %s\n", argv[i]);
    929 			return -1;
    930 		}
    931 	}
    932 
    933 	rv = flash_cmd(ec, EC_CMD_USB_PD_CONTROL, 1, &p, sizeof(p),
    934 			&r, sizeof(r));
    935 
    936 	if (rv < 0 || argc != 2)
    937 		return (rv < 0) ? rv : 0;
    938 
    939 	printf("Port C%d is %s,%s, Role:%s %s%s Polarity:CC%d State:%s\n",
    940 	       p.port, (r.enabled & 1) ? "enabled" : "disabled",
    941 	       (r.enabled & 2) ? "connected" : "disconnected",
    942 	       r.role & PD_ROLE_SOURCE ? "SRC" : "SNK",
    943 	       r.role & (PD_ROLE_DFP << 1) ? "DFP" : "UFP",
    944 	       r.role & (1 << 2) ? " VCONN" : "",
    945 	       r.polarity + 1, r.state);
    946 
    947 	return (rv < 0 ? rv : 0);
    948 }
    949 
    950 static void print_pd_power_info(struct ec_response_usb_pd_power_info *r)
    951 {
    952 	switch (r->role) {
    953 	case USB_PD_PORT_POWER_DISCONNECTED:
    954 		printf("Disconnected");
    955 		break;
    956 	case USB_PD_PORT_POWER_SOURCE:
    957 		printf("SRC");
    958 		break;
    959 	case USB_PD_PORT_POWER_SINK:
    960 		printf("SNK");
    961 		break;
    962 	case USB_PD_PORT_POWER_SINK_NOT_CHARGING:
    963 		printf("SNK (not charging)");
    964 		break;
    965 	default:
    966 		printf("Unknown");
    967 	}
    968 
    969 	if ((r->role == USB_PD_PORT_POWER_DISCONNECTED) ||
    970 	    (r->role == USB_PD_PORT_POWER_SOURCE)) {
    971 		printf("\n");
    972 		return;
    973 	}
    974 
    975 	printf(r->dualrole ? " DRP" : " Charger");
    976 	switch (r->type) {
    977 	case USB_CHG_TYPE_PD:
    978 		printf(" PD");
    979 		break;
    980 	case USB_CHG_TYPE_C:
    981 		printf(" Type-C");
    982 		break;
    983 	case USB_CHG_TYPE_PROPRIETARY:
    984 		printf(" Proprietary");
    985 		break;
    986 	case USB_CHG_TYPE_BC12_DCP:
    987 		printf(" DCP");
    988 		break;
    989 	case USB_CHG_TYPE_BC12_CDP:
    990 		printf(" CDP");
    991 		break;
    992 	case USB_CHG_TYPE_BC12_SDP:
    993 		printf(" SDP");
    994 		break;
    995 	case USB_CHG_TYPE_OTHER:
    996 		printf(" Other");
    997 		break;
    998 	case USB_CHG_TYPE_VBUS:
    999 		printf(" VBUS");
   1000 		break;
   1001 	case USB_CHG_TYPE_UNKNOWN:
   1002 		printf(" Unknown");
   1003 		break;
   1004 	}
   1005 	printf(" %dmV / %dmA, max %dmV / %dmA",
   1006 		r->meas.voltage_now, r->meas.current_lim, r->meas.voltage_max,
   1007 		r->meas.current_max);
   1008 	if (r->max_power)
   1009 		printf(" / %dmW", r->max_power / 1000);
   1010 	printf("\n");
   1011 }
   1012 
   1013 static int cmd_ec_usbpdpower(int argc, const char **argv)
   1014 {
   1015 	struct ec_params_usb_pd_power_info p;
   1016 	struct ec_response_usb_pd_power_info r;
   1017 	struct ec_response_usb_pd_ports rp;
   1018 	int i, rv;
   1019 
   1020 	if (!get_ec())
   1021 		return -ENODEV;
   1022 
   1023 	rv = flash_cmd(ec, EC_CMD_USB_PD_PORTS, 0, NULL, 0, &rp, sizeof(rp));
   1024 	if (rv)
   1025 		return rv;
   1026 
   1027 	for (i = 0; i < rp.num_ports; i++) {
   1028 		p.port = i;
   1029 		rv = flash_cmd(ec, EC_CMD_USB_PD_POWER_INFO, 0,
   1030 				&p, sizeof(p), &r, sizeof(r));
   1031 		if (rv)
   1032 			return rv;
   1033 
   1034 		printf("Port %d: ", i);
   1035 		print_pd_power_info(&r);
   1036 	}
   1037 
   1038 	return 0;
   1039 }
   1040 
   1041 static int cmd_ec_version(int argc, const char **argv)
   1042 {
   1043         static const char * const image_names[] = {"unknown", "RO", "RW"};
   1044 	struct ec_response_get_version r;
   1045 	char build_string[128];
   1046 	int rv;
   1047 
   1048 	if (!get_ec())
   1049 		return -ENODEV;
   1050 
   1051 	rv = flash_cmd(ec, EC_CMD_GET_VERSION, 0, NULL, 0, &r, sizeof(r));
   1052 	if (rv < 0) {
   1053 		fprintf(stderr, "ERROR: EC_CMD_GET_VERSION failed: %d\n", rv);
   1054 		return rv;
   1055 	}
   1056 	rv = flash_cmd(ec, EC_CMD_GET_BUILD_INFO, 0,
   1057 			NULL, 0, build_string, sizeof(build_string));
   1058 	if (rv < 0) {
   1059 		fprintf(stderr, "ERROR: EC_CMD_GET_BUILD_INFO failed: %d\n",
   1060 				rv);
   1061 		return rv;
   1062 	}
   1063 
   1064 	/* Ensure versions are null-terminated before we print them */
   1065 	r.version_string_ro[sizeof(r.version_string_ro) - 1] = '\0';
   1066 	r.version_string_rw[sizeof(r.version_string_rw) - 1] = '\0';
   1067 	build_string[sizeof(build_string) - 1] = '\0';
   1068 
   1069 	/* Print versions */
   1070 	printf("RO version:    %s\n", r.version_string_ro);
   1071 	printf("RW version:    %s\n", r.version_string_rw);
   1072 	printf("Firmware copy: %s\n",
   1073 	       (r.current_image < ARRAY_SIZE(image_names) ?
   1074 		image_names[r.current_image] : "?"));
   1075 	printf("Build info:    %s\n", build_string);
   1076 
   1077 	return 0;
   1078 }
   1079 
   1080 struct command subcmds_ec[] = {
   1081 	CMD(ec_battery, "Show battery status"),
   1082 	CMD(ec_bq25892, "Dump the state of the bq25892 charger chip"),
   1083 	CMD(ec_bq27742, "Dump the state of the bq27742 gas gauge"),
   1084 	CMD(ec_chargecontrol, "Force the battery to stop charging/discharge"),
   1085 	CMD(ec_console, "Prints the last output to the EC debug console"),
   1086 	CMD(ec_gpioget, "Get the value of GPIO signal"),
   1087 	CMD(ec_gpioset, "Set the value of GPIO signal"),
   1088 	CMD(ec_echash, "Various EC hash commands"),
   1089 	CMD(ec_lightbar, "Lightbar control commands"),
   1090 	CMD(ec_pi3usb9281, "Dump the state of the Pericom PI3USB9281 chip"),
   1091 	CMD(ec_usbpd, "Control USB PD/type-C"),
   1092 	CMD(ec_usbpdpower, "Power information about USB PD ports"),
   1093 	CMD(ec_version, "Prints EC version"),
   1094 	CMD_GUARD_LAST
   1095 };
   1096