summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2015-04-03 18:16:53 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-04-07 03:41:09 +0000
commit30572cb5063aff322138de9466b11044b6f9a178 (patch)
treef2e36e2f9b831ebfff557ebc635b5d0bc86cdd9a
parent2d2d1e15cfd3a91c6d624d380ce44945855d0c83 (diff)
downloadchrome-ec-30572cb5063aff322138de9466b11044b6f9a178.tar.gz
samus: create USB PD device whitelist for allowing charging
Create a USB PD device whitelist for allowing charging by default from dual-role devices that don't set the externally powered bit. BUG=chrome-os-partner:38785 BRANCH=samus TEST=modify zinger and modify VID and PID to match white-listed entry. also modify zinger to remove externally powered bit and set dual-role power bits so that we treat as a dual-role device by default. when you plug in this modified zinger into samus, it still will not charge because the VID and PID are obtained after deciding to treat it as dual-role, but when you issue soft reset "pd 1 soft", it starts charging. the white-listed device will always ask for a power swap if it is a sink, so we will always get source cap after learning the VID/PID, which should correctly trigger changing the device to be treated as a dedicated charger. Change-Id: Ibe7ec57f842a0b9bfb02447baf5b3327217a9516 Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/264015 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--common/usb_pd_policy.c16
-rw-r--r--common/usb_pd_protocol.c28
-rw-r--r--include/usb_pd.h22
3 files changed, 58 insertions, 8 deletions
diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c
index 4d712542e8..3a620eb1f1 100644
--- a/common/usb_pd_policy.c
+++ b/common/usb_pd_policy.c
@@ -175,6 +175,17 @@ unsigned pd_get_max_voltage(void)
{
return max_request_mv;
}
+
+int pd_charge_from_device(uint16_t vid, uint16_t pid)
+{
+ /* TODO: rewrite into table if we get more of these */
+ /*
+ * White-list Apple charge-through accessory since it doesn't set
+ * externally powered bit, but we still need to charge from it when
+ * we are a sink.
+ */
+ return (vid == USB_VID_APPLE && pid == 0x1012);
+}
#endif /* CONFIG_USB_PD_DUAL_ROLE */
#ifdef CONFIG_USB_PD_ALT_MODE
@@ -436,6 +447,11 @@ uint16_t pd_get_identity_vid(int port)
return PD_IDH_VID(pe[port].identity[0]);
}
+uint16_t pd_get_identity_pid(int port)
+{
+ return PD_PRODUCT_PID(pe[port].identity[2]);
+}
+
#ifdef CONFIG_CMD_USB_PD_PE
static void dump_pe(int port)
{
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 01da41cdaa..01225f255b 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -944,6 +944,17 @@ static void pd_send_request_msg(int port, int always_send_request)
static void pd_update_pdo_flags(int port, uint32_t pdo)
{
+#ifdef CONFIG_CHARGE_MANAGER
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+ int charge_whitelisted =
+ (pd[port].power_role == PD_ROLE_SINK &&
+ pd_charge_from_device(pd_get_identity_vid(port),
+ pd_get_identity_pid(port)));
+#else
+ const int charge_whitelisted = 0;
+#endif
+#endif
+
/* can only parse PDO flags if type is fixed */
if ((pdo & PDO_TYPE_MASK) != PDO_TYPE_FIXED)
return;
@@ -967,16 +978,17 @@ static void pd_update_pdo_flags(int port, uint32_t pdo)
#ifdef CONFIG_CHARGE_MANAGER
/*
- * If partner supports power swap and is NOT externally powered, then
- * treat this as a dualrole device. Otherwise, treat this as a
- * dedicated charger.
+ * Treat device as a dedicated charger (meaning we should charge
+ * from it) if it does not support power swap, or if it is externally
+ * powered, or if we are a sink and the device identity matches a
+ * charging white-list.
*/
- if ((pd[port].flags & PD_FLAGS_PARTNER_DR_POWER) &&
- !(pd[port].flags & PD_FLAGS_PARTNER_EXTPOWER)) {
- charge_manager_update_dualrole(port, CAP_DUALROLE);
- } else {
+ if (!(pd[port].flags & PD_FLAGS_PARTNER_DR_POWER) ||
+ (pd[port].flags & PD_FLAGS_PARTNER_EXTPOWER) ||
+ charge_whitelisted)
charge_manager_update_dualrole(port, CAP_DEDICATED);
- }
+ else
+ charge_manager_update_dualrole(port, CAP_DUALROLE);
#endif
}
diff --git a/include/usb_pd.h b/include/usb_pd.h
index ebed5c3554..75b0967406 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -573,6 +573,9 @@ struct pd_policy {
/* USB Vendor ID assigned to Google Inc. */
#define USB_VID_GOOGLE 0x18d1
+/* Other Vendor IDs */
+#define USB_VID_APPLE 0x05ac
+
/* Timeout for message receive in microseconds */
#define USB_PD_RX_TMOUT_US 1800
@@ -922,6 +925,17 @@ void pd_check_pr_role(int port, int pr_role, int flags);
void pd_check_dr_role(int port, int dr_role, int flags);
/**
+ * Check if we should charge from this device. This is
+ * basically a white-list for chargers that are dual-role,
+ * don't set the externally powered bit, but we should charge
+ * from by default.
+ *
+ * @param vid Port partner Vendor ID
+ * @param pid Port partner Product ID
+ */
+int pd_charge_from_device(uint16_t vid, uint16_t pid);
+
+/**
* Execute data swap.
*
* @param port USB-C port number
@@ -1004,6 +1018,14 @@ void pd_dfp_pe_init(int port);
uint16_t pd_get_identity_vid(int port);
/**
+ * Return the PID of the USB PD accessory connected to a specified port
+ *
+ * @param port USB-C port number
+ * @return the USB Product Identifier or 0 if it doesn't exist
+ */
+uint16_t pd_get_identity_pid(int port);
+
+/**
* Store Device ID & RW hash of device
*
* @param port USB-C port number