Parcourir la source

Support the HV_Preferred flag

Now when we make a request from a voltage range, if the HV_Preferred
flag is enabled, we iterate over the PDOs backwards, so we see
higher-voltage fixed supply PDOs before lower-voltage ones.  This causes
the flag to do what it's supposed to.

The code to find a PDO from the range has been factored out into its own
function which will be used when building a Sink_Capabilities message.
Clara Hobbs il y a 6 ans
Parent
révision
b05795350f
1 fichiers modifiés avec 64 ajouts et 32 suppressions
  1. 64
    32
      src/device_policy_manager.c

+ 64
- 32
src/device_policy_manager.c Voir le fichier

@@ -31,6 +31,45 @@
31 31
 /* The current draw when the output is disabled */
32 32
 #define DPM_MIN_CURRENT PD_MA2PDI(100)
33 33
 
34
+
35
+/*
36
+ * Find the index of the first PDO from capabilities in the voltage range,
37
+ * using the desired order.
38
+ *
39
+ * If there is no such PDO, returns -1 instead.
40
+ */
41
+static int8_t dpm_get_range_fixed_pdo_index(const union pd_msg *capabilities,
42
+        struct pdbs_config *scfg)
43
+{
44
+    /* Get the number of PDOs */
45
+    uint8_t numobj = PD_NUMOBJ_GET(capabilities);
46
+
47
+    /* Get ready to iterate over the PDOs */
48
+    int8_t i;
49
+    int8_t step;
50
+    if (scfg->flags & PDBS_CONFIG_FLAGS_HV_PREFERRED) {
51
+        i = numobj - 1;
52
+        step = -1;
53
+    } else {
54
+        i = 0;
55
+        step = 1;
56
+    }
57
+
58
+    /* Look at the PDOs to see if one falls in our voltage range. */
59
+    while (0 <= i && i < numobj) {
60
+        /* If we have a fixed PDO, its V is within our range, and its I is at
61
+         * least our desired I */
62
+        if ((capabilities->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED
63
+                && PD_PDO_SRC_FIXED_CURRENT_GET(capabilities, i) >= scfg->i
64
+                && PD_PDO_SRC_FIXED_VOLTAGE_GET(capabilities, i) >= PD_MV2PDV(scfg->vmin)
65
+                && PD_PDO_SRC_FIXED_VOLTAGE_GET(capabilities, i) <= PD_MV2PDV(scfg->vmax)) {
66
+            return i;
67
+        }
68
+        i += step;
69
+    }
70
+    return -1;
71
+}
72
+
34 73
 bool pdbs_dpm_evaluate_capability(struct pdb_config *cfg,
35 74
         const union pd_msg *capabilities, union pd_msg *request)
36 75
 {
@@ -121,40 +160,33 @@ bool pdbs_dpm_evaluate_capability(struct pdb_config *cfg,
121 160
                 return true;
122 161
             }
123 162
         }
124
-        /* Look at the PDOs a second time to see if one falls in our voltage
125
-         * range. */
126
-        for (uint8_t i = 0; i < numobj; i++) {
127
-            /* If we have a fixed PDO, its V equals our desired V, and its I is
128
-             * at least our desired I */
129
-            if ((capabilities->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED
130
-                    && PD_PDO_SRC_FIXED_CURRENT_GET(capabilities, i) >= scfg->i
131
-                    && PD_PDO_SRC_FIXED_VOLTAGE_GET(capabilities, i) >= PD_MV2PDV(scfg->vmin)
132
-                    && PD_PDO_SRC_FIXED_VOLTAGE_GET(capabilities, i) <= PD_MV2PDV(scfg->vmax)) {
133
-                /* We got what we wanted, so build a request for that */
134
-                request->hdr = cfg->pe.hdr_template | PD_MSGTYPE_REQUEST
135
-                    | PD_NUMOBJ(1);
136
-                if (scfg->flags & PDBS_CONFIG_FLAGS_GIVEBACK) {
137
-                    /* GiveBack enabled */
138
-                    request->obj[0] = PD_RDO_FV_MIN_CURRENT_SET(DPM_MIN_CURRENT)
139
-                        | PD_RDO_FV_CURRENT_SET(scfg->i)
140
-                        | PD_RDO_NO_USB_SUSPEND | PD_RDO_GIVEBACK
141
-                        | PD_RDO_OBJPOS_SET(i + 1);
142
-                } else {
143
-                    /* GiveBack disabled */
144
-                    request->obj[0] = PD_RDO_FV_MAX_CURRENT_SET(scfg->i)
145
-                        | PD_RDO_FV_CURRENT_SET(scfg->i)
146
-                        | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(i + 1);
147
-                }
148
-                if (dpm_data->usb_comms) {
149
-                    request->obj[0] |= PD_RDO_USB_COMMS;
150
-                }
163
+        /* If there's a PDO in the voltage range, use it */
164
+        int8_t i = dpm_get_range_fixed_pdo_index(capabilities, scfg);
165
+        if (i >= 0) {
166
+            /* We got what we wanted, so build a request for that */
167
+            request->hdr = cfg->pe.hdr_template | PD_MSGTYPE_REQUEST
168
+                | PD_NUMOBJ(1);
169
+            if (scfg->flags & PDBS_CONFIG_FLAGS_GIVEBACK) {
170
+                /* GiveBack enabled */
171
+                request->obj[0] = PD_RDO_FV_MIN_CURRENT_SET(DPM_MIN_CURRENT)
172
+                    | PD_RDO_FV_CURRENT_SET(scfg->i)
173
+                    | PD_RDO_NO_USB_SUSPEND | PD_RDO_GIVEBACK
174
+                    | PD_RDO_OBJPOS_SET(i + 1);
175
+            } else {
176
+                /* GiveBack disabled */
177
+                request->obj[0] = PD_RDO_FV_MAX_CURRENT_SET(scfg->i)
178
+                    | PD_RDO_FV_CURRENT_SET(scfg->i)
179
+                    | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(i + 1);
180
+            }
181
+            if (dpm_data->usb_comms) {
182
+                request->obj[0] |= PD_RDO_USB_COMMS;
183
+            }
151 184
 
152
-                /* Update requested voltage */
153
-                dpm_data->_requested_voltage = PD_PDV2MV(PD_PDO_SRC_FIXED_VOLTAGE_GET(capabilities, i));
185
+            /* Update requested voltage */
186
+            dpm_data->_requested_voltage = PD_PDV2MV(PD_PDO_SRC_FIXED_VOLTAGE_GET(capabilities, i));
154 187
 
155
-                dpm_data->_capability_match = true;
156
-                return true;
157
-            }
188
+            dpm_data->_capability_match = true;
189
+            return true;
158 190
         }
159 191
     }
160 192
     /* Nothing matched (or no configuration), so get 5 V at low current */

Chargement…
Annuler
Enregistrer