static int cmd_ec_gpioset(int argc, const char **argv) { struct ec_params_gpio_set p; char *e; int rv; if (!get_ec()) return -ENODEV; if (argc != 3) { fprintf(stderr, "Usage: %s <GPIO name> <0 | 1>\n", argv[0]); return -1; } if (strlen(argv[1]) + 1 > sizeof(p.name)) { fprintf(stderr, "GPIO name too long.\n"); return -1; } strcpy(p.name, argv[1]); p.val = strtol(argv[2], &e, 0); if (e && *e) { fprintf(stderr, "Bad value.\n"); return -1; } rv = flash_cmd(ec, EC_CMD_GPIO_SET, 0, &p, sizeof(p), NULL, 0); if (rv < 0) return rv; printf("GPIO %s set to %d\n", p.name, p.val); return 0; }
static int cmd_ec_console(int argc, const char **argv) { char data[128]; int rv; if (!get_ec()) return -ENODEV; /* Snapshot the EC console */ rv = flash_cmd(ec, EC_CMD_CONSOLE_SNAPSHOT, 0, NULL, 0, NULL, 0); if (rv < 0) return rv; /* Loop and read from the snapshot until it's done */ while (1) { memset(data, 0, sizeof(data)); rv = flash_cmd(ec, EC_CMD_CONSOLE_READ, 0, NULL, 0, data, sizeof(data)); if (rv) return rv; /* Empty response means done */ if (!data[0]) break; /* Make sure output is null-terminated, then dump it */ data[sizeof(data) - 1] = '\0'; fputs(data, stdout); } printf("\n"); return 0; }
static int cmd_ec_usbpdpower(int argc, const char **argv) { struct ec_params_usb_pd_power_info p; struct ec_response_usb_pd_power_info r; struct ec_response_usb_pd_ports rp; int i, rv; if (!get_ec()) return -ENODEV; rv = flash_cmd(ec, EC_CMD_USB_PD_PORTS, 0, NULL, 0, &rp, sizeof(rp)); if (rv) return rv; for (i = 0; i < rp.num_ports; i++) { p.port = i; rv = flash_cmd(ec, EC_CMD_USB_PD_POWER_INFO, 0, &p, sizeof(p), &r, sizeof(r)); if (rv) return rv; printf("Port %d: ", i); print_pd_power_info(&r); } return 0; }
int sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v) { EC_POINT *pt = EC_POINT_new(EC_KEY_get0_group(v)); int r; const u_char *d; size_t len; if (pt == NULL) { SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL")); return SSH_ERR_ALLOC_FAIL; } if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0) { EC_POINT_free(pt); return r; } if ((r = get_ec(d, len, pt, EC_KEY_get0_group(v))) != 0) { EC_POINT_free(pt); return r; } if (EC_KEY_set_public_key(v, pt) != 1) { EC_POINT_free(pt); return SSH_ERR_ALLOC_FAIL; /* XXX assumption */ } EC_POINT_free(pt); /* Skip string */ if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) { /* Shouldn't happen */ SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); SSHBUF_ABORT(); return SSH_ERR_INTERNAL_ERROR; } return 0; }
static int bq27742_read(int reg, int size, int *value) { int rv; struct ec_response_i2c_read r; struct ec_params_i2c_read p = { .port = 0, .read_size = size, .addr = BQ27742_ADDR, .offset = reg }; rv = flash_cmd(ec, EC_CMD_I2C_READ, 0, &p, sizeof(p), &r, sizeof(r)); if (rv < 0) { *value = -1; return rv; } *value = r.data; return 0; } static int bq27742_write(int reg, int size, int value) { int rv; struct ec_params_i2c_write p = { .port = 0, .write_size = size, .addr = BQ27742_ADDR, .offset = reg, .data = value }; rv = flash_cmd(ec, EC_CMD_I2C_WRITE, 0, &p, sizeof(p), NULL, 0); return rv < 0 ? rv : 0; } static int cmd_ec_bq27742(int argc, const char **argv) { int i; int value; int rv; int chg_mv, chg_ma; if (!get_ec()) return -ENODEV; /* Get chip ID in Control subcommand DEVICE_TYPE (0x1) */ bq27742_write(BQ27742_REG_CTRL, 16, 0x1); bq27742_read(BQ27742_REG_CTRL, 16, &value); printf("ID: BQ27%3x\n", value); bq27742_read(BQ27742_REG_CHARGING_MV, 16, &chg_mv); bq27742_read(BQ27742_REG_CHARGING_MA, 16, &chg_ma); printf("Requested charge: %d mV %d mA\n", chg_mv, chg_ma); bq27742_read(BQ27742_REG_FLAGS, 16, &value); printf("Flags: %04x\n", value); bq27742_read(BQ27742_REG_PROTECTOR, 8, &value); printf("ProtectorState: %02x\n", value); return 0; }
static int cmd_ec_battery(int argc, const char **argv) { char batt_text[EC_MEMMAP_TEXT_MAX + 1]; uint32_t val; if (!get_ec()) return -ENODEV; printf("Battery info:\n"); val = ec_readmem8(EC_MEMMAP_BATTERY_VERSION); if (val < 1) { fprintf(stderr, "Battery version %d is not supported\n", val); return -EINVAL; } memset(batt_text, 0, EC_MEMMAP_TEXT_MAX + 1); ec_readmem(EC_MEMMAP_BATT_MFGR, sizeof(batt_text), batt_text); printf(" OEM name: %s\n", batt_text); ec_readmem(EC_MEMMAP_BATT_MODEL, sizeof(batt_text), batt_text); printf(" Model number: %s\n", batt_text); printf(" Chemistry : %s\n", batt_text); ec_readmem(EC_MEMMAP_BATT_SERIAL, sizeof(batt_text), batt_text); printf(" Serial number: %s\n", batt_text); val = ec_readmem32(EC_MEMMAP_BATT_DCAP); printf(" Design capacity: %u mAh\n", val); val = ec_readmem32(EC_MEMMAP_BATT_LFCC); printf(" Last full charge: %u mAh\n", val); val = ec_readmem32(EC_MEMMAP_BATT_DVLT); printf(" Design output voltage %u mV\n", val); val = ec_readmem32(EC_MEMMAP_BATT_CCNT); printf(" Cycle count %u\n", val); val = ec_readmem32(EC_MEMMAP_BATT_VOLT); printf(" Present voltage %u mV\n", val); val = ec_readmem32(EC_MEMMAP_BATT_RATE); printf(" Present current %u mA\n", val); val = ec_readmem32(EC_MEMMAP_BATT_CAP); printf(" Remaining capacity %u mAh\n", val); val = ec_readmem8(EC_MEMMAP_BATT_FLAG); printf(" Flags 0x%02x", val); if (val & EC_BATT_FLAG_AC_PRESENT) printf(" AC_PRESENT"); if (val & EC_BATT_FLAG_BATT_PRESENT) printf(" BATT_PRESENT"); if (val & EC_BATT_FLAG_DISCHARGING) printf(" DISCHARGING"); if (val & EC_BATT_FLAG_CHARGING) printf(" CHARGING"); if (val & EC_BATT_FLAG_LEVEL_CRITICAL) printf(" LEVEL_CRITICAL"); printf("\n"); return 0; }
static int cmd_ec_chargecontrol(int argc, const char **argv) { struct ec_params_charge_control p; int rv; if (argc != 2) { fprintf(stderr, "Usage: %s <normal | idle | discharge>\n", argv[0]); return -EINVAL; } if (!strcasecmp(argv[1], "normal")) { p.mode = CHARGE_CONTROL_NORMAL; } else if (!strcasecmp(argv[1], "idle")) { p.mode = CHARGE_CONTROL_IDLE; } else if (!strcasecmp(argv[1], "discharge")) { p.mode = CHARGE_CONTROL_DISCHARGE; } else { fprintf(stderr, "Bad value.\n"); return -EINVAL; } if (!get_ec()) return -ENODEV; rv = flash_cmd(ec, EC_CMD_CHARGE_CONTROL, 1, &p, sizeof(p), NULL, 0); if (rv < 0) { fprintf(stderr, "Is AC connected?\n"); return rv; } switch (p.mode) { case CHARGE_CONTROL_NORMAL: printf("Charge state machine normal mode.\n"); break; case CHARGE_CONTROL_IDLE: printf("Charge state machine force idle.\n"); break; case CHARGE_CONTROL_DISCHARGE: printf("Charge state machine force discharge.\n"); break; default: break; } return 0; }
int sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g) { const u_char *d; size_t len; int r; if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0) return r; if ((r = get_ec(d, len, v, g)) != 0) return r; /* Skip string */ if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) { /* Shouldn't happen */ SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); SSHBUF_ABORT(); return SSH_ERR_INTERNAL_ERROR; } return 0; }
static int cmd_ec_version(int argc, const char **argv) { static const char * const image_names[] = {"unknown", "RO", "RW"}; struct ec_response_get_version r; char build_string[128]; int rv; if (!get_ec()) return -ENODEV; rv = flash_cmd(ec, EC_CMD_GET_VERSION, 0, NULL, 0, &r, sizeof(r)); if (rv < 0) { fprintf(stderr, "ERROR: EC_CMD_GET_VERSION failed: %d\n", rv); return rv; } rv = flash_cmd(ec, EC_CMD_GET_BUILD_INFO, 0, NULL, 0, build_string, sizeof(build_string)); if (rv < 0) { fprintf(stderr, "ERROR: EC_CMD_GET_BUILD_INFO failed: %d\n", rv); return rv; } /* Ensure versions are null-terminated before we print them */ r.version_string_ro[sizeof(r.version_string_ro) - 1] = '\0'; r.version_string_rw[sizeof(r.version_string_rw) - 1] = '\0'; build_string[sizeof(build_string) - 1] = '\0'; /* Print versions */ printf("RO version: %s\n", r.version_string_ro); printf("RW version: %s\n", r.version_string_rw); printf("Firmware copy: %s\n", (r.current_image < ARRAY_SIZE(image_names) ? image_names[r.current_image] : "?")); printf("Build info: %s\n", build_string); return 0; }
static int cmd_ec_usbpd(int argc, const char **argv) { const char *role_str[] = {"", "toggle", "toggle-off", "sink", "source"}; const char *mux_str[] = {"", "none", "usb", "dp", "dock", "auto"}; const char *swap_str[] = {"", "dr_swap", "pr_swap", "vconn_swap"}; struct ec_params_usb_pd_control p; struct ec_response_usb_pd_control_v1 r; int rv, i; unsigned j; int option_ok; char *e; if (!get_ec()) return -ENODEV; p.role = USB_PD_CTRL_ROLE_NO_CHANGE; p.mux = USB_PD_CTRL_MUX_NO_CHANGE; p.swap = USB_PD_CTRL_SWAP_NONE; if (argc < 2) { fprintf(stderr, "No port specified.\n"); return -1; } p.port = strtol(argv[1], &e, 0); if (e && *e) { fprintf(stderr, "Invalid param (port)\n"); return -1; } for (i = 2; i < argc; ++i) { option_ok = 0; if (!strcmp(argv[i], "auto")) { if (argc != 3) { fprintf(stderr, "\"auto\" may not be used " "with other options.\n"); return -1; } p.role = USB_PD_CTRL_ROLE_TOGGLE_ON; p.mux = USB_PD_CTRL_MUX_AUTO; continue; } for (j = 0; j < ARRAY_SIZE(role_str); ++j) { if (!strcmp(argv[i], role_str[j])) { if (p.role != USB_PD_CTRL_ROLE_NO_CHANGE) { fprintf(stderr, "Only one role allowed.\n"); return -1; } p.role = j; option_ok = 1; break; } } if (option_ok) continue; for (j = 0; j < ARRAY_SIZE(mux_str); ++j) { if (!strcmp(argv[i], mux_str[j])) { if (p.mux != USB_PD_CTRL_MUX_NO_CHANGE) { fprintf(stderr, "Only one mux type allowed.\n"); return -1; } p.mux = j; option_ok = 1; break; } } if (option_ok) continue; for (j = 0; j < ARRAY_SIZE(swap_str); ++j) { if (!strcmp(argv[i], swap_str[j])) { if (p.swap != USB_PD_CTRL_SWAP_NONE) { fprintf(stderr, "Only one swap type allowed.\n"); return -1; } p.swap = j; option_ok = 1; break; } } if (!option_ok) { fprintf(stderr, "Unknown option: %s\n", argv[i]); return -1; } } rv = flash_cmd(ec, EC_CMD_USB_PD_CONTROL, 1, &p, sizeof(p), &r, sizeof(r)); if (rv < 0 || argc != 2) return (rv < 0) ? rv : 0; printf("Port C%d is %s,%s, Role:%s %s%s Polarity:CC%d State:%s\n", p.port, (r.enabled & 1) ? "enabled" : "disabled", (r.enabled & 2) ? "connected" : "disconnected", r.role & PD_ROLE_SOURCE ? "SRC" : "SNK", r.role & (PD_ROLE_DFP << 1) ? "DFP" : "UFP", r.role & (1 << 2) ? " VCONN" : "", r.polarity + 1, r.state); return (rv < 0 ? rv : 0); }
static int pi3usb9281_read(int reg, int *value) { int rv; struct ec_response_i2c_read r; struct ec_params_i2c_read p = { .port = 0, .read_size = 8, .addr = PI3USB9281_ADDR, .offset = reg }; rv = flash_cmd(ec, EC_CMD_I2C_READ, 0, &p, sizeof(p), &r, sizeof(r)); if (rv < 0) { *value = -1; return rv; } *value = r.data; return 0; } static int cmd_ec_pi3usb9281(int argc, const char **argv) { unsigned i; int value; int rv; int dev_type, chg_stat, vbus; char *apple_chg = "", *proprio_chg = ""; if (!get_ec()) return -ENODEV; pi3usb9281_read(PI3USB9281_REG_DEV_TYPE, &dev_type); pi3usb9281_read(PI3USB9281_REG_CHG_STATUS, &chg_stat); pi3usb9281_read(PI3USB9281_REG_VBUS, &vbus); switch((chg_stat>>2)&7) { case 4: apple_chg = "Apple 2.4A"; break; case 2: apple_chg = "Apple 2A"; break; case 1: apple_chg = "Apple 1A"; break; } switch(chg_stat&3) { case 3: proprio_chg = "type-2"; break; case 2: proprio_chg = "type-1"; break; case 1: proprio_chg = "rsvd"; break; } printf("USB: %s%s%s%s%s%s Charger: %s%s VBUS: %d\n", dev_type & (1<<6) ? "DCP" : " ", dev_type & (1<<5) ? "CDP" : " ", dev_type & (1<<4) ? "CarKit" : " ", dev_type & (1<<2) ? "SDP" : " ", dev_type & (1<<1) ? "OTG" : " ", dev_type & (1<<0) ? "MHL" : " ", apple_chg, proprio_chg, !!(vbus & 2)); printf("REG:"); for (i = 0; i < PI3USB9281_COUNT; ++i) printf(" %02x", pi3usb9281_regs[i]); printf("\n"); printf("VAL:"); for (i = 0; i < PI3USB9281_COUNT; ++i) { rv = pi3usb9281_read(pi3usb9281_regs[i], &value); if (rv) return rv; printf(" %02x", value); } printf("\n"); return 0; }
static int cmd_ec_lightbar(int argc, const char **argv) { unsigned i; int r; struct ec_params_lightbar param; struct ec_response_lightbar resp; if (!get_ec()) return -ENODEV; if (1 == argc) { /* no args = dump 'em all */ r = lb_do_cmd(LIGHTBAR_CMD_DUMP, ¶m, &resp); if (r) return r; for (i = 0; i < ARRAY_SIZE(resp.dump.vals); i++) { printf(" %02x %02x %02x\n", resp.dump.vals[i].reg, resp.dump.vals[i].ic0, resp.dump.vals[i].ic1); } return 0; } if (argc == 2 && !strcasecmp(argv[1], "init")) return lb_do_cmd(LIGHTBAR_CMD_INIT, ¶m, &resp); if (argc == 2 && !strcasecmp(argv[1], "off")) return lb_do_cmd(LIGHTBAR_CMD_OFF, ¶m, &resp); if (argc == 2 && !strcasecmp(argv[1], "on")) return lb_do_cmd(LIGHTBAR_CMD_ON, ¶m, &resp); if (!strcasecmp(argv[1], "version")) { r = lb_do_cmd(LIGHTBAR_CMD_VERSION, ¶m, &resp); if (!r) printf("version %d flags 0x%x\n", resp.version.num, resp.version.flags); return r; } if (argc > 1 && !strcasecmp(argv[1], "brightness")) { char *e; int rv; if (argc > 2) { param.set_brightness.num = 0xff & strtoul(argv[2], &e, 16); return lb_do_cmd(LIGHTBAR_CMD_SET_BRIGHTNESS, ¶m, &resp); } rv = lb_do_cmd(LIGHTBAR_CMD_GET_BRIGHTNESS, ¶m, &resp); if (rv) return rv; printf("%02x\n", resp.get_brightness.num); return 0; } if (argc > 1 && !strcasecmp(argv[1], "demo")) { int rv; if (argc > 2) { if (!strcasecmp(argv[2], "on") || argv[2][0] == '1') param.demo.num = 1; else if (!strcasecmp(argv[2], "off") || argv[2][0] == '0') param.demo.num = 0; else { fprintf(stderr, "Invalid arg\n"); return -1; } return lb_do_cmd(LIGHTBAR_CMD_DEMO, ¶m, &resp); } rv = lb_do_cmd(LIGHTBAR_CMD_GET_DEMO, ¶m, &resp); if (rv) return rv; printf("%s\n", resp.get_demo.num ? "on" : "off"); return 0; } if (argc > 2 && !strcasecmp(argv[1], "seq")) { char *e; uint8_t num; num = 0xff & strtoul(argv[2], &e, 16); if (e && *e) { if (!strcasecmp(argv[2], "stop")) num = 0x8; else if (!strcasecmp(argv[2], "run")) num = 0x9; else if (!strcasecmp(argv[2], "konami")) num = 0xA; else num = LIGHTBAR_NUM_SEQUENCES; } if (num >= LIGHTBAR_NUM_SEQUENCES) { fprintf(stderr, "Invalid arg\n"); return -1; } param.seq.num = num; return lb_do_cmd(LIGHTBAR_CMD_SEQ, ¶m, &resp); } if (argc == 4) { char *e; param.reg.ctrl = 0xff & strtoul(argv[1], &e, 16); param.reg.reg = 0xff & strtoul(argv[2], &e, 16); param.reg.value = 0xff & strtoul(argv[3], &e, 16); return lb_do_cmd(LIGHTBAR_CMD_REG, ¶m, &resp); } if (argc == 5) { char *e; param.set_rgb.led = strtoul(argv[1], &e, 16); param.set_rgb.red = strtoul(argv[2], &e, 16); param.set_rgb.green = strtoul(argv[3], &e, 16); param.set_rgb.blue = strtoul(argv[4], &e, 16); return lb_do_cmd(LIGHTBAR_CMD_SET_RGB, ¶m, &resp); } /* Only thing left is to try to read an LED value */ if (argc == 2) { char *e; param.get_rgb.led = strtoul(argv[1], &e, 0); if (!(e && *e)) { r = lb_do_cmd(LIGHTBAR_CMD_GET_RGB, ¶m, &resp); if (r) return r; printf("%02x %02x %02x\n", resp.get_rgb.red, resp.get_rgb.green, resp.get_rgb.blue); return 0; } } return 0; }
static int cmd_ec_echash(int argc, const char **argv) { struct ec_params_vboot_hash p; struct ec_response_vboot_hash r; char *e; int rv; if (!get_ec()) return -ENODEV; if (argc < 2) { /* Get hash status */ p.cmd = EC_VBOOT_HASH_GET; rv = flash_cmd(ec, EC_CMD_VBOOT_HASH, 0, &p, sizeof(p), &r, sizeof(r)); if (rv < 0) return rv; return ec_hash_print(&r); } if (argc == 2 && !strcasecmp(argv[1], "abort")) { /* Abort hash calculation */ p.cmd = EC_VBOOT_HASH_ABORT; rv = flash_cmd(ec, EC_CMD_VBOOT_HASH, 0, &p, sizeof(p), &r, sizeof(r)); return (rv < 0 ? rv : 0); } /* The only other commands are start and recalc */ if (!strcasecmp(argv[1], "start")) p.cmd = EC_VBOOT_HASH_START; else if (!strcasecmp(argv[1], "recalc")) p.cmd = EC_VBOOT_HASH_RECALC; else return -EINVAL; p.hash_type = EC_VBOOT_HASH_TYPE_SHA256; if (argc < 3) { fprintf(stderr, "Must specify offset\n"); return -1; } if (!strcasecmp(argv[2], "ro")) { p.offset = EC_VBOOT_HASH_OFFSET_RO; p.size = 0; printf("Hashing EC-RO...\n"); } else if (!strcasecmp(argv[2], "rw")) { p.offset = EC_VBOOT_HASH_OFFSET_RW; p.size = 0; printf("Hashing EC-RW...\n"); } else if (argc < 4) { fprintf(stderr, "Must specify size\n"); return -1; } else { p.offset = strtol(argv[2], &e, 0); if (e && *e) { fprintf(stderr, "Bad offset.\n"); return -1; } p.size = strtol(argv[3], &e, 0); if (e && *e) { fprintf(stderr, "Bad size.\n"); return -1; } printf("Hashing %d bytes at offset %d...\n", p.size, p.offset); } if (argc == 5) { /* * Technically nonce can be any binary data up to 64 bytes, * but this command only supports a 32-bit value. */ uint32_t nonce = strtol(argv[4], &e, 0); if (e && *e) { fprintf(stderr, "Bad nonce integer.\n"); return -1; } memcpy(p.nonce_data, &nonce, sizeof(nonce)); p.nonce_size = sizeof(nonce); } else p.nonce_size = 0; rv = flash_cmd(ec, EC_CMD_VBOOT_HASH, 0, &p, sizeof(p), &r, sizeof(r)); if (rv < 0) return rv; /* Start command doesn't wait for hashing to finish */ if (p.cmd == EC_VBOOT_HASH_START) return 0; /* Recalc command does wait around, so a result is ready now */ return ec_hash_print(&r); }
static int cmd_ec_gpioget(int argc, const char **argv) { struct ec_params_gpio_get_v1 p_v1; struct ec_response_gpio_get_v1 r_v1; int i, rv, subcmd, num_gpios; if (!get_ec()) return -ENODEV; if (argc > 2) { printf("Usage: %s [<subcmd> <GPIO name>]\n", argv[0]); printf("'gpioget <GPIO_NAME>' - Get value by name\n"); printf("'gpioget count' - Get count of GPIOS\n"); printf("'gpioget all' - Get info for all GPIOs\n"); return -1; } /* Keeping it consistent with console command behavior */ if (argc == 1) subcmd = EC_GPIO_GET_INFO; else if (!strcmp(argv[1], "count")) subcmd = EC_GPIO_GET_COUNT; else if (!strcmp(argv[1], "all")) subcmd = EC_GPIO_GET_INFO; else subcmd = EC_GPIO_GET_BY_NAME; if (subcmd == EC_GPIO_GET_BY_NAME) { p_v1.subcmd = EC_GPIO_GET_BY_NAME; if (strlen(argv[1]) + 1 > sizeof(p_v1.get_value_by_name.name)) { fprintf(stderr, "GPIO name too long.\n"); return -1; } strcpy(p_v1.get_value_by_name.name, argv[1]); rv = flash_cmd(ec, EC_CMD_GPIO_GET, 1, &p_v1, sizeof(p_v1), &r_v1, sizeof(r_v1)); if (rv < 0) return rv; printf("GPIO %s = %d\n", p_v1.get_value_by_name.name, r_v1.get_value_by_name.val); return 0; } /* Need GPIO count for EC_GPIO_GET_COUNT or EC_GPIO_GET_INFO */ p_v1.subcmd = EC_GPIO_GET_COUNT; rv = flash_cmd(ec, EC_CMD_GPIO_GET, 1, &p_v1, sizeof(p_v1), &r_v1, sizeof(r_v1)); if (rv < 0) return rv; if (subcmd == EC_GPIO_GET_COUNT) { printf("GPIO COUNT = %d\n", r_v1.get_count.val); return 0; } /* subcmd EC_GPIO_GET_INFO */ num_gpios = r_v1.get_count.val; p_v1.subcmd = EC_GPIO_GET_INFO; for (i = 0; i < num_gpios; i++) { p_v1.get_info.index = i; rv = flash_cmd(ec, EC_CMD_GPIO_GET, 1, &p_v1, sizeof(p_v1), &r_v1, sizeof(r_v1)); if (rv < 0) return rv; printf("%2d %-32s 0x%04X\n", r_v1.get_info.val, r_v1.get_info.name, r_v1.get_info.flags); } return 0; }
static int bq25892_read(int reg, int *value) { int rv; struct ec_response_i2c_read r; struct ec_params_i2c_read p = { .port = 0, .read_size = 8, .addr = BQ2589X_ADDR, .offset = reg }; rv = flash_cmd(ec, EC_CMD_I2C_READ, 0, &p, sizeof(p), &r, sizeof(r)); if (rv < 0) { *value = -1; return rv; } *value = r.data; return 0; } static int bq25892_write(int reg, int value) { int rv; struct ec_params_i2c_write p = { .port = 0, .write_size = 8, .addr = BQ2589X_ADDR, .offset = reg, .data = value }; rv = flash_cmd(ec, EC_CMD_I2C_WRITE, 0, &p, sizeof(p), NULL, 0); return rv < 0 ? rv : 0; } static int cmd_ec_bq25892(int argc, const char **argv) { int i; int value; int rv; int batt_mv, sys_mv, vbus_mv, chg_ma, input_ma; if (!get_ec()) return -ENODEV; /* Trigger one ADC conversion */ bq25892_read(BQ2589X_REG_CFG1, &value); bq25892_write(BQ2589X_REG_CFG1, value | BQ2589X_CFG1_CONV_START); do { rv = bq25892_read(BQ2589X_REG_CFG1, &value); } while ((value & BQ2589X_CFG1_CONV_START) || (rv < 0)); bq25892_read(BQ2589X_REG_ADC_BATT_VOLT, &batt_mv); bq25892_read(BQ2589X_REG_ADC_SYS_VOLT, &sys_mv); bq25892_read(BQ2589X_REG_ADC_VBUS_VOLT, &vbus_mv); bq25892_read(BQ2589X_REG_ADC_CHG_CURR, &chg_ma); bq25892_read(BQ2589X_REG_ADC_INPUT_CURR, &input_ma); printf("ADC Batt %dmV Sys %dmV VBUS %dmV Chg %dmA Input %dmA\n", 2304 + (batt_mv & 0x7f) * 20, 2304 + sys_mv * 20, 2600 + (vbus_mv & 0x7f) * 100, chg_ma * 50, 100 + (input_ma & 0x3f) * 50); printf("REG:"); for (i = 0; i <= 0x14; ++i) printf(" %02x", i); printf("\n"); printf("VAL:"); for (i = 0; i <= 0x14; ++i) { rv = bq25892_read(i, &value); if (rv) return rv; printf(" %02x", value); } printf("\n"); return 0; }