|
@@ -49,12 +49,16 @@ enum policy_engine_state {
|
49
|
49
|
static union pd_msg *policy_engine_message = NULL;
|
50
|
50
|
/* Whether or not the source capabilities match our required power */
|
51
|
51
|
static bool capability_match = false;
|
|
52
|
+/* Whether or not we have an explicit contract */
|
|
53
|
+static bool explicit_contract = false;
|
52
|
54
|
/* Policy Engine thread mailbox */
|
53
|
55
|
static msg_t pdb_pe_mailbox_queue[PDB_MSG_POOL_SIZE];
|
54
|
56
|
mailbox_t pdb_pe_mailbox;
|
55
|
57
|
|
56
|
58
|
static enum policy_engine_state pe_sink_startup(void)
|
57
|
59
|
{
|
|
60
|
+ explicit_contract = false;
|
|
61
|
+
|
58
|
62
|
/* No need to reset the protocol layer here. There are two ways into this
|
59
|
63
|
* state: startup and exiting hard reset. On startup, the protocol layer
|
60
|
64
|
* is reset by the startup procedure. When exiting hard reset, the
|
|
@@ -154,8 +158,27 @@ static enum policy_engine_state pe_sink_select_cap(void)
|
154
|
158
|
chPoolFree(&pdb_msg_pool, policy_engine_message);
|
155
|
159
|
policy_engine_message = NULL;
|
156
|
160
|
return PESinkSoftReset;
|
157
|
|
- /* TODO: Wait and Reject messages should be recognized here */
|
|
161
|
+ /* If the message was Wait or Reject */
|
|
162
|
+ } else if ((PD_MSGTYPE_GET(policy_engine_message) == PD_MSGTYPE_REJECT
|
|
163
|
+ || PD_MSGTYPE_GET(policy_engine_message) == PD_MSGTYPE_WAIT)
|
|
164
|
+ && PD_NUMOBJ_GET(policy_engine_message) == 0) {
|
|
165
|
+ /* If we don't have an explicit contract, wait for capabilities */
|
|
166
|
+ if (!explicit_contract) {
|
|
167
|
+ chPoolFree(&pdb_msg_pool, policy_engine_message);
|
|
168
|
+ policy_engine_message = NULL;
|
|
169
|
+ return PESinkWaitCap;
|
|
170
|
+ /* If we do have an explicit contract, go to the ready state */
|
|
171
|
+ } else {
|
|
172
|
+ /* TODO: we should take note if we got here from a Wait
|
|
173
|
+ * message, because we Should run the SinkRequestTimer in the
|
|
174
|
+ * Ready state if that's the case. */
|
|
175
|
+ chPoolFree(&pdb_msg_pool, policy_engine_message);
|
|
176
|
+ policy_engine_message = NULL;
|
|
177
|
+ return PESinkReady;
|
|
178
|
+ }
|
158
|
179
|
} else {
|
|
180
|
+ chPoolFree(&pdb_msg_pool, policy_engine_message);
|
|
181
|
+ policy_engine_message = NULL;
|
159
|
182
|
return PESinkSendSoftReset;
|
160
|
183
|
}
|
161
|
184
|
}
|
|
@@ -176,6 +199,9 @@ static enum policy_engine_state pe_sink_transition_sink(void)
|
176
|
199
|
/* If we got a PS_RDY, handle it */
|
177
|
200
|
if (PD_MSGTYPE_GET(policy_engine_message) == PD_MSGTYPE_PS_RDY
|
178
|
201
|
&& PD_NUMOBJ_GET(policy_engine_message) == 0) {
|
|
202
|
+ /* We just finished negotiating an explicit contract */
|
|
203
|
+ explicit_contract = true;
|
|
204
|
+
|
179
|
205
|
/* Set the output appropriately */
|
180
|
206
|
if (capability_match) {
|
181
|
207
|
pdb_dpm_output_on();
|
|
@@ -344,6 +370,8 @@ static enum policy_engine_state pe_sink_hard_reset(void)
|
344
|
370
|
|
345
|
371
|
static enum policy_engine_state pe_sink_transition_default(void)
|
346
|
372
|
{
|
|
373
|
+ explicit_contract = false;
|
|
374
|
+
|
347
|
375
|
/* Tell the DPM to turn off the output */
|
348
|
376
|
pdb_dpm_output_off();
|
349
|
377
|
|