summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2015-01-02 14:06:54 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-01-03 02:26:42 +0000
commit71fb0f9e11d3d1b4a7b2026994f2003815dd2799 (patch)
tree1e2c3640706ac76f1d99c736a1a125e39e8dc342
parent017f151ea36a3309aec05ace79916ab3dae35ac1 (diff)
downloadchrome-ec-71fb0f9e11d3d1b4a7b2026994f2003815dd2799.tar.gz
pd: add new state to wait for getSinkCap response
Add new state to wait for getSinkCap response. We use the READY states in the PD state machine to indicate that we are not waiting on a response. This assumption is necessary for VDMs to know whether or not it is ok to send. This CL fixes a bug in that assumption. BUG=chrome-os-partner:33861 BRANCH=samus TEST=load onto zinger. without this change, under the right circumstances it was possible for a collision between a VDM (response to discover identity) and an incoming response to the getSinkCap. This would cause the discovery identity response to get dropped. with this change, when discover identity response is queued it is delayed until after the getSinkCap response. Change-Id: I16f4d5272e68bf699d0aecba12bdf6d6b8ff7fc7 Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/238239 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--common/usb_pd_protocol.c13
-rw-r--r--include/usb_pd.h1
2 files changed, 13 insertions, 1 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 4ae13bd127..dae4ae789f 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -938,6 +938,8 @@ static void handle_data_request(int port, uint16_t head,
pd[port].flags |= PD_FLAGS_SNK_CAP_RECVD;
/* snk cap 0 should be fixed PDO */
pd_update_pdo_flags(port, payload[0]);
+ if (pd[port].task_state == PD_STATE_SRC_GET_SINK_CAP)
+ set_state(port, PD_STATE_SRC_READY);
break;
case PD_DATA_VENDOR_DEF:
handle_vdm_request(port, cnt, payload);
@@ -1821,6 +1823,7 @@ void pd_task(void)
!(pd[port].flags & PD_FLAGS_SNK_CAP_RECVD)) {
/* Get sink cap to know if dual-role device */
send_control(port, PD_CTRL_GET_SINK_CAP);
+ set_state(port, PD_STATE_SRC_GET_SINK_CAP);
pd[port].flags &= ~PD_FLAGS_GET_SNK_CAP_SENT;
break;
}
@@ -1861,6 +1864,13 @@ void pd_task(void)
set_state(port, PD_STATE_SOFT_RESET);
timeout = 10 * MSEC;
break;
+ case PD_STATE_SRC_GET_SINK_CAP:
+ if (pd[port].last_state != pd[port].task_state)
+ set_state_timeout(port,
+ get_time().val +
+ PD_T_SENDER_RESPONSE,
+ PD_STATE_SRC_READY);
+ break;
case PD_STATE_SRC_DR_SWAP:
if (pd[port].last_state != pd[port].task_state) {
res = send_control(port, PD_CTRL_DR_SWAP);
@@ -2747,7 +2757,8 @@ static int command_pd(int argc, char **argv)
"SRC_DISCONNECTED", "SRC_HARD_RESET_RECOVER",
"SRC_STARTUP", "SRC_DISCOVERY",
"SRC_NEGOCIATE", "SRC_ACCEPTED", "SRC_POWERED",
- "SRC_TRANSITION", "SRC_READY", "SRC_DR_SWAP",
+ "SRC_TRANSITION", "SRC_READY", "SRC_GET_SNK_CAP",
+ "SRC_DR_SWAP",
#ifdef CONFIG_USB_PD_DUAL_ROLE
"SRC_SWAP_INIT", "SRC_SWAP_SNK_DISABLE",
"SRC_SWAP_SRC_DISABLE", "SRC_SWAP_STANDBY",
diff --git a/include/usb_pd.h b/include/usb_pd.h
index 13e8a982e2..f04281140e 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -576,6 +576,7 @@ enum pd_states {
PD_STATE_SRC_POWERED,
PD_STATE_SRC_TRANSITION,
PD_STATE_SRC_READY,
+ PD_STATE_SRC_GET_SINK_CAP,
PD_STATE_SRC_DR_SWAP,
#ifdef CONFIG_USB_PD_DUAL_ROLE