|
@@ -27,6 +27,15 @@
|
27
|
27
|
#include "fusb302b.h"
|
28
|
28
|
|
29
|
29
|
|
|
30
|
+static void pe_sink_pps_periodic_timer_cb(void *cfg)
|
|
31
|
+{
|
|
32
|
+ /* Signal the PE thread to make a new PPS request */
|
|
33
|
+ chSysLockFromISR();
|
|
34
|
+ chEvtSignalI(((struct pdb_config *) cfg)->pe.thread, PDB_EVT_PE_PPS_REQUEST);
|
|
35
|
+ chSysUnlockFromISR();
|
|
36
|
+}
|
|
37
|
+
|
|
38
|
+
|
30
|
39
|
enum policy_engine_state {
|
31
|
40
|
PESinkStartup,
|
32
|
41
|
PESinkDiscovery,
|
|
@@ -133,6 +142,21 @@ static enum policy_engine_state pe_sink_wait_cap(struct pdb_config *cfg)
|
133
|
142
|
|
134
|
143
|
static enum policy_engine_state pe_sink_eval_cap(struct pdb_config *cfg)
|
135
|
144
|
{
|
|
145
|
+ /* If we have a message, remember the index of the first PPS APDO so we can
|
|
146
|
+ * check if the request is for a PPS APDO in PE_SNK_Select_Cap. */
|
|
147
|
+ if (cfg->pe._message != NULL) {
|
|
148
|
+ /* Start by assuming we won't find a PPS APDO (set the index greater
|
|
149
|
+ * than the maximum possible) */
|
|
150
|
+ cfg->pe._pps_index = 8;
|
|
151
|
+ /* Search for the first PPS APDO */
|
|
152
|
+ for (int8_t i = 0; i < PD_NUMOBJ_GET(cfg->pe._message); i++) {
|
|
153
|
+ if ((cfg->pe._message->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED
|
|
154
|
+ && (cfg->pe._message->obj[i] & PD_APDO_TYPE) == PD_APDO_TYPE_PPS) {
|
|
155
|
+ cfg->pe._pps_index = i + 1;
|
|
156
|
+ break;
|
|
157
|
+ }
|
|
158
|
+ }
|
|
159
|
+ }
|
136
|
160
|
/* Get a message object for the request if we don't have one already */
|
137
|
161
|
if (cfg->pe._last_dpm_request == NULL) {
|
138
|
162
|
cfg->pe._last_dpm_request = chPoolAlloc(&pdb_msg_pool);
|
|
@@ -165,6 +189,20 @@ static enum policy_engine_state pe_sink_select_cap(struct pdb_config *cfg)
|
165
|
189
|
return PESinkHardReset;
|
166
|
190
|
}
|
167
|
191
|
|
|
192
|
+ /* If we're using PD 3.0 */
|
|
193
|
+ if ((cfg->pe.hdr_template & PD_HDR_SPECREV) == PD_SPECREV_3_0) {
|
|
194
|
+ /* If the request was for a PPS APDO, start SinkPPSPeriodicTimer */
|
|
195
|
+ if (PD_RDO_OBJPOS_GET(cfg->pe._last_dpm_request) >= cfg->pe._pps_index) {
|
|
196
|
+ chVTSet(&cfg->pe._sink_pps_periodic_timer, PD_T_PPS_REQUEST,
|
|
197
|
+ pe_sink_pps_periodic_timer_cb, cfg);
|
|
198
|
+ /* Otherwise, stop SinkPPSPeriodicTimer */
|
|
199
|
+ } else {
|
|
200
|
+ chVTReset(&cfg->pe._sink_pps_periodic_timer);
|
|
201
|
+ }
|
|
202
|
+ }
|
|
203
|
+ /* This will use a virtual timer to send an event flag to this thread after
|
|
204
|
+ * PD_T_PPS_REQUEST */
|
|
205
|
+
|
168
|
206
|
/* Wait for a response */
|
169
|
207
|
evt = chEvtWaitAnyTimeout(PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET,
|
170
|
208
|
PD_T_SENDER_RESPONSE);
|
|
@@ -278,11 +316,12 @@ static enum policy_engine_state pe_sink_ready(struct pdb_config *cfg)
|
278
|
316
|
if (cfg->pe._min_power) {
|
279
|
317
|
evt = chEvtWaitAnyTimeout(PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET
|
280
|
318
|
| PDB_EVT_PE_I_OVRTEMP | PDB_EVT_PE_GET_SOURCE_CAP
|
281
|
|
- | PDB_EVT_PE_NEW_POWER, PD_T_SINK_REQUEST);
|
|
319
|
+ | PDB_EVT_PE_NEW_POWER | PDB_EVT_PE_PPS_REQUEST,
|
|
320
|
+ PD_T_SINK_REQUEST);
|
282
|
321
|
} else {
|
283
|
322
|
evt = chEvtWaitAny(PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET
|
284
|
323
|
| PDB_EVT_PE_I_OVRTEMP | PDB_EVT_PE_GET_SOURCE_CAP
|
285
|
|
- | PDB_EVT_PE_NEW_POWER);
|
|
324
|
+ | PDB_EVT_PE_NEW_POWER | PDB_EVT_PE_PPS_REQUEST);
|
286
|
325
|
}
|
287
|
326
|
|
288
|
327
|
/* If we got reset signaling, transition to default */
|
|
@@ -313,6 +352,11 @@ static enum policy_engine_state pe_sink_ready(struct pdb_config *cfg)
|
313
|
352
|
return PESinkEvalCap;
|
314
|
353
|
}
|
315
|
354
|
|
|
355
|
+ /* If SinkPPSPeriodicTimer ran out, send a new request */
|
|
356
|
+ if (evt & PDB_EVT_PE_PPS_REQUEST) {
|
|
357
|
+ return PESinkSelectCap;
|
|
358
|
+ }
|
|
359
|
+
|
316
|
360
|
/* If no event was received, the timer ran out. */
|
317
|
361
|
if (evt == 0) {
|
318
|
362
|
/* Repeat our Request message */
|
|
@@ -720,8 +764,12 @@ static THD_FUNCTION(PolicyEngine, vcfg) {
|
720
|
764
|
|
721
|
765
|
/* Initialize the mailbox */
|
722
|
766
|
chMBObjectInit(&cfg->pe.mailbox, cfg->pe._mailbox_queue, PDB_MSG_POOL_SIZE);
|
|
767
|
+ /* Initialize the VT for SinkPPSPeriodicTimer */
|
|
768
|
+ chVTObjectInit(&cfg->pe._sink_pps_periodic_timer);
|
723
|
769
|
/* Initialize the old_tcc_match */
|
724
|
770
|
cfg->pe._old_tcc_match = -1;
|
|
771
|
+ /* Initialize the pps_index */
|
|
772
|
+ cfg->pe._pps_index = 8;
|
725
|
773
|
/* Initialize the PD message header template */
|
726
|
774
|
cfg->pe.hdr_template = PD_DATAROLE_UFP | PD_POWERROLE_SINK;
|
727
|
775
|
|