diff options
author | Eric Yilun Lin <yllin@chromium.org> | 2021-01-13 15:07:27 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-01-14 05:08:36 +0000 |
commit | c4ad6ccf5d64e1af3abbaba257781ff02ee2a7ef (patch) | |
tree | 11e2d517b8dc1f9c7122882d212a3a744863df02 /common/usb_pd_alt_mode_dfp.c | |
parent | e26814fbbfb2c89ae4971b4707bbc836f3e8aa3f (diff) | |
download | chrome-ec-c4ad6ccf5d64e1af3abbaba257781ff02ee2a7ef.tar.gz |
USB-PD: filter duplicated SVID
We have seen some peripherals may broadcast duplicated SVID, and
this might cause the SM in a weird state in that the SVID disocvering
traverses sequentially by pd_get_next_mode(), and this cause
the SM discovering SVID modes over and over again.
We filter out the duplicated SVID to prevent such scenario.
BUG=b:177285652
TEST=Plug adapter ADLX65YCC3A, and ensure no repeated
discover_mode for NAKed SVIDs.
BRANCH=none
Change-Id: I68811be039e214c5045fb71bb7025bcc6226a051
Signed-off-by: Eric Yilun Lin <yllin@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2626795
Reviewed-by: Diana Z <dzigterman@chromium.org>
Diffstat (limited to 'common/usb_pd_alt_mode_dfp.c')
-rw-r--r-- | common/usb_pd_alt_mode_dfp.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/common/usb_pd_alt_mode_dfp.c b/common/usb_pd_alt_mode_dfp.c index 8f2643ff1d..5a7ed7052b 100644 --- a/common/usb_pd_alt_mode_dfp.c +++ b/common/usb_pd_alt_mode_dfp.c @@ -302,6 +302,23 @@ int pd_dfp_exit_mode(int port, enum tcpm_transmit_type type, uint16_t svid, return 1; } +/* + * Check if the SVID has been recorded previously. Some peripherals provide + * duplicated SVID. + */ +static bool is_svid_duplicated(const struct pd_discovery *disc, uint16_t svid) +{ + int i; + + for (i = 0; i < disc->svid_cnt; ++i) + if (disc->svids[i].svid == svid) { + CPRINTF("ERR:SVIDDUP\n"); + return true; + } + + return false; +} + void dfp_consume_attention(int port, uint32_t *payload) { uint16_t svid = PD_VDO_VID(payload[0]); @@ -383,14 +400,17 @@ void dfp_consume_svids(int port, enum tcpm_transmit_type type, int cnt, svid0 = PD_VDO_SVID_SVID0(*ptr); if (!svid0) break; - disc->svids[i].svid = svid0; - disc->svid_cnt++; + + if (!is_svid_duplicated(disc, svid0)) + disc->svids[disc->svid_cnt++].svid = svid0; svid1 = PD_VDO_SVID_SVID1(*ptr); if (!svid1) break; - disc->svids[i + 1].svid = svid1; - disc->svid_cnt++; + + if (!is_svid_duplicated(disc, svid1)) + disc->svids[disc->svid_cnt++].svid = svid1; + ptr++; vdo++; } |