Browse Source

Add get_source_cap command

It prints the most recently advertised PDOs in a reasonable format.  The
types it doesn't know about are printed as hex so that someone
knowledgeable can still get the information they need.  For now, it only
knows about fixed PDOs, so variable and battery PDOs will be shown as
hex.

Since this means we remember the most recent Source_Capabilities, it's
now becoming possible to send a new Request without sending a
Get_Source_Cap message first.  That's not actually done yet, but I'd
like to do it that way.  I'd also at some point like to make a
lower-current Request when the PD Buddy Sink's output is disabled, but
again, that's still to come.
Clara Hobbs 6 years ago
parent
commit
cea3f92e63
4 changed files with 110 additions and 4 deletions
  1. 10
    2
      src/device_policy_manager.c
  2. 3
    0
      src/device_policy_manager.h
  3. 4
    2
      src/policy_engine.c
  4. 93
    0
      src/shell.c

+ 10
- 2
src/device_policy_manager.c View File

@@ -29,11 +29,11 @@
29 29
 
30 30
 
31 31
 bool pdb_dpm_output_enabled = true;
32
-
33 32
 bool pdb_dpm_led_pd_status = true;
34
-
35 33
 bool pdb_dpm_usb_comms = false;
36 34
 
35
+const union pd_msg *pdb_dpm_capabilities = NULL;
36
+
37 37
 
38 38
 /* The current draw when the output is disabled */
39 39
 #define DPM_MIN_CURRENT PD_MA2PDI(100)
@@ -49,6 +49,14 @@ static int dpm_requested_voltage;
49 49
 
50 50
 bool pdb_dpm_evaluate_capability(const union pd_msg *capabilities, union pd_msg *request)
51 51
 {
52
+    /* Update the stored Source_Capabilities */
53
+    if (capabilities != NULL) {
54
+        if (pdb_dpm_capabilities != NULL) {
55
+            chPoolFree(&pdb_msg_pool, (union pd_msg *) pdb_dpm_capabilities);
56
+        }
57
+        pdb_dpm_capabilities = capabilities;
58
+    }
59
+
52 60
     /* Get the current configuration */
53 61
     struct pdb_config *cfg = pdb_config_flash_read();
54 62
     /* Get the number of PDOs */

+ 3
- 0
src/device_policy_manager.h View File

@@ -33,6 +33,9 @@ extern bool pdb_dpm_led_pd_status;
33 33
 /* Whether the device is capable of USB communications */
34 34
 extern bool pdb_dpm_usb_comms;
35 35
 
36
+/* The most recently received Source_Capabilities message */
37
+extern const union pd_msg *pdb_dpm_capabilities;
38
+
36 39
 
37 40
 /*
38 41
  * Create a Request message based on the given Source_Capabilities message.

+ 4
- 2
src/policy_engine.c View File

@@ -142,8 +142,10 @@ static enum policy_engine_state pe_sink_eval_cap(void)
142 142
     /* Ask the DPM what to request */
143 143
     capability_match = pdb_dpm_evaluate_capability(policy_engine_message,
144 144
             last_dpm_request);
145
-    /* Free the Source_Capabilities message */
146
-    chPoolFree(&pdb_msg_pool, policy_engine_message);
145
+    /* It's up to the DPM to free the Source_Capabilities message, which it can
146
+     * do whenever it sees fit.  Just remove our reference to it since we won't
147
+     * know when it's no longer valid. */
148
+    policy_engine_message = NULL;
147 149
 
148 150
     return PESinkSelectCap;
149 151
 }

+ 93
- 0
src/shell.c View File

@@ -52,6 +52,77 @@ static struct pdb_config tmpcfg = {
52 52
     .status = PDB_CONFIG_STATUS_VALID
53 53
 };
54 54
 
55
+/*
56
+ * Helper functions for printing PDOs
57
+ */
58
+static void print_src_fixed_pdo(BaseSequentialStream *chp, uint32_t pdo)
59
+{
60
+    int tmp;
61
+
62
+    chprintf(chp, "\ttype: fixed\r\n");
63
+
64
+    /* Dual-role power */
65
+    tmp = (pdo & PD_PDO_SRC_FIXED_DUAL_ROLE_PWR) >> PD_PDO_SRC_FIXED_DUAL_ROLE_PWR_SHIFT;
66
+    if (tmp) {
67
+        chprintf(chp, "\tdual_role_pwr: %d\r\n", tmp);
68
+    }
69
+
70
+    /* USB Suspend Supported */
71
+    tmp = (pdo & PD_PDO_SRC_FIXED_USB_SUSPEND) >> PD_PDO_SRC_FIXED_USB_SUSPEND_SHIFT;
72
+    if (tmp) {
73
+        chprintf(chp, "\tusb_suspend: %d\r\n", tmp);
74
+    }
75
+
76
+    /* Unconstrained power */
77
+    tmp = (pdo & PD_PDO_SRC_FIXED_UNCONSTRAINED) >> PD_PDO_SRC_FIXED_UNCONSTRAINED_SHIFT;
78
+    if (tmp) {
79
+        chprintf(chp, "\tunconstrained_pwr: %d\r\n", tmp);
80
+    }
81
+
82
+    /* USB communications capable */
83
+    tmp = (pdo & PD_PDO_SRC_FIXED_USB_COMMS) >> PD_PDO_SRC_FIXED_USB_COMMS_SHIFT;
84
+    if (tmp) {
85
+        chprintf(chp, "\tusb_comms: %d\r\n", tmp);
86
+    }
87
+
88
+    /* Dual-role data */
89
+    tmp = (pdo & PD_PDO_SRC_FIXED_DUAL_ROLE_DATA) >> PD_PDO_SRC_FIXED_DUAL_ROLE_DATA_SHIFT;
90
+    if (tmp) {
91
+        chprintf(chp, "\tdual_role_data: %d\r\n", tmp);
92
+    }
93
+
94
+    /* Peak current */
95
+    tmp = (pdo & PD_PDO_SRC_FIXED_PEAK_CURRENT) >> PD_PDO_SRC_FIXED_PEAK_CURRENT_SHIFT;
96
+    if (tmp) {
97
+        chprintf(chp, "\tpeak_i: %d\r\n", tmp);
98
+    }
99
+
100
+    /* Voltage */
101
+    tmp = (pdo & PD_PDO_SRC_FIXED_VOLTAGE) >> PD_PDO_SRC_FIXED_VOLTAGE_SHIFT;
102
+    chprintf(chp, "\tv: %d.%02d V\r\n", PD_PDV_V(tmp), PD_PDV_CV(tmp));
103
+
104
+    /* Maximum current */
105
+    tmp = (pdo & PD_PDO_SRC_FIXED_CURRENT) >> PD_PDO_SRC_FIXED_CURRENT_SHIFT;
106
+    chprintf(chp, "\ti: %d.%02d A\r\n", PD_PDI_A(tmp), PD_PDI_CA(tmp));
107
+}
108
+
109
+static void print_src_pdo(BaseSequentialStream *chp, uint32_t pdo, uint8_t index)
110
+{
111
+    /* If we have a positive index, print a label for the PDO */
112
+    if (index) {
113
+        chprintf(chp, "PDO %d:\r\n", index);
114
+    }
115
+
116
+    /* Select the appropriate method for printing the PDO itself */
117
+    if ((pdo & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED) {
118
+        print_src_fixed_pdo(chp, pdo);
119
+    } else {
120
+        /* Unknown PDO, just print it as hex */
121
+        chprintf(chp, "\t%08X\r\n", pdo);
122
+    }
123
+}
124
+
125
+
55 126
 /*
56 127
  * Command functions
57 128
  */
@@ -272,6 +343,27 @@ static void cmd_output(BaseSequentialStream *chp, int argc, char *argv[])
272 343
     }
273 344
 }
274 345
 
346
+static void cmd_get_source_cap(BaseSequentialStream *chp, int argc, char *argv[])
347
+{
348
+    (void) argv;
349
+    if (argc > 0) {
350
+        chprintf(chp, "Usage: get_source_cap\r\n");
351
+        return;
352
+    }
353
+
354
+    /* If we haven't seen any Source_Capabilities yet, bail out now */
355
+    if (pdb_dpm_capabilities == NULL) {
356
+        chprintf(chp, "No Source_Capabilities\r\n");
357
+        return;
358
+    }
359
+
360
+    /* Print all the PDOs */
361
+    uint8_t numobj = PD_NUMOBJ_GET(pdb_dpm_capabilities);
362
+    for (uint8_t i = 0; i < numobj; i++) {
363
+        print_src_pdo(chp, pdb_dpm_capabilities->obj[i], i+1);
364
+    }
365
+}
366
+
275 367
 /*
276 368
  * List of shell commands
277 369
  */
@@ -290,6 +382,7 @@ static const struct pdb_shell_cmd commands[] = {
290 382
     /* TODO {"set_v_range", cmd_set_v_range, "Set the minimum and maximum voltage in millivolts"},*/
291 383
     {"identify", cmd_identify, "Blink the LED to identify the device"},
292 384
     {"output", cmd_output, "Get or set the output status"},
385
+    {"get_source_cap", cmd_get_source_cap, "Print the capabilities of the PD source"},
293 386
     {NULL, NULL, NULL}
294 387
 };
295 388
 

Loading…
Cancel
Save