/** * Perform cleanup operations on an override port, when switching to a * different port. This involves switching the port from sink to source, * if applicable. */ static void charge_manager_cleanup_override_port(int port) { if (port < 0 || port >= CONFIG_USB_PD_PORT_COUNT) return; if (dualrole_capability[port] == CAP_DUALROLE && pd_get_role(port) == PD_ROLE_SINK) pd_request_power_swap(port); }
/** * Attempt to switch to power source on port if applicable. */ static void charge_manager_switch_to_source(int port) { if (port < 0 || port >= CONFIG_USB_PD_PORT_COUNT) return; /* If connected to dual-role device, then ask for a swap */ if (dualrole_capability[port] == CAP_DUALROLE && pd_get_role(port) == PD_ROLE_SINK) pd_request_power_swap(port); }
/** * Select an 'override port', a port which is always the preferred charge port. * Returns EC_SUCCESS on success, ec_error_list status on failure. * * @param port Charge port to select as override, or * OVERRIDE_OFF to select no override port, * or OVERRIDE_DONT_CHARGE to specifc that no * charge port should be selected. */ int charge_manager_set_override(int port) { int retval = EC_SUCCESS; ASSERT(port >= OVERRIDE_DONT_CHARGE && port < CONFIG_USB_PD_PORT_COUNT); CPRINTS("Charge Override: %d", port); /* Supersede any pending delayed overrides. */ if (delayed_override_port != OVERRIDE_OFF) { if (delayed_override_port != port) charge_manager_cleanup_override_port( delayed_override_port); delayed_override_port = OVERRIDE_OFF; hook_call_deferred( charge_override_timeout, -1); } /* Set the override port if it's a sink. */ if (port < 0 || pd_get_role(port) == PD_ROLE_SINK) { if (override_port != port) { charge_manager_cleanup_override_port(override_port); override_port = port; if (charge_manager_is_seeded()) hook_call_deferred(charge_manager_refresh, 0); } } /* * If the attached device is capable of being a sink, request a * power swap and set the delayed override for swap completion. */ else if (pd_get_role(port) != PD_ROLE_SINK && dualrole_capability[port] == CAP_DUALROLE) { delayed_override_deadline.val = get_time().val + POWER_SWAP_TIMEOUT; delayed_override_port = port; hook_call_deferred( charge_override_timeout, POWER_SWAP_TIMEOUT); pd_request_power_swap(port); /* Can't charge from requested port -- return error. */ } else retval = EC_ERROR_INVAL; return retval; }
void pd_check_pr_role(int port, int pr_role, int flags) { /* * If partner is dual-role power and dualrole toggling is on, consider * if a power swap is necessary. */ if ((flags & PD_FLAGS_PARTNER_DR_POWER) && pd_get_dual_role() == PD_DRP_TOGGLE_ON) { /* * If we are source and partner is externally powered, * swap to become a sink. */ if ((flags & PD_FLAGS_PARTNER_EXTPOWER) && pr_role == PD_ROLE_SOURCE) pd_request_power_swap(port); } }
/** * Select an 'override port', a port which is always the preferred charge port. * Returns EC_SUCCESS on success, ec_error_list status on failure. * * @param port Charge port to select as override, or * OVERRIDE_OFF to select no override port, * or OVERRIDE_DONT_CHARGE to specifc that no * charge port should be selected. */ int charge_manager_set_override(int port) { int retval = EC_SUCCESS; ASSERT(port >= OVERRIDE_DONT_CHARGE && port < CONFIG_USB_PD_PORT_COUNT); CPRINTS("Charge Override: %d", port); /* * If attempting to change the override port, then return * error. Since we may be in the middle of a power swap on * the original override port, it's too complicated to * guarantee that the original override port is switched back * to source. */ if (delayed_override_port != OVERRIDE_OFF) return EC_ERROR_BUSY; /* Set the override port if it's a sink. */ if (port < 0 || pd_get_role(port) == PD_ROLE_SINK) { if (override_port != port) { override_port = port; if (charge_manager_is_seeded()) hook_call_deferred(charge_manager_refresh, 0); } } /* * If the attached device is capable of being a sink, request a * power swap and set the delayed override for swap completion. */ else if (pd_get_role(port) != PD_ROLE_SINK && dualrole_capability[port] == CAP_DUALROLE) { delayed_override_deadline.val = get_time().val + POWER_SWAP_TIMEOUT; delayed_override_port = port; hook_call_deferred( charge_override_timeout, POWER_SWAP_TIMEOUT); pd_request_power_swap(port); /* Can't charge from requested port -- return error. */ } else retval = EC_ERROR_INVAL; return retval; }