88#include <stdlib.h>
99#include <errno.h>
1010
11- static void usage_cap_short (void ) {
11+ static void
12+ usage_cap_short (void ) {
1213 fprintf (stderr ,
1314"capability get\n"
14- "capability check [--need-pec on|off] [--min-speed 100|400] [--need-alert on|off] [--strict]\n"
15+ "capability check [--need-pec on|off] [--min-speed 100|400|1000] [--need-alert on|off]\n"
16+ " [--need-fp on|off] [--need-avsbus on|off] [--strict]\n"
1517"capability help\n"
1618 );
1719}
1820
19- static void usage_cap_long (void ) {
21+ static void
22+ usage_cap_long (void ) {
2023 fprintf (stderr ,
2124"\n"
2225"NAME\n"
2326" capability — Decode PMBUS_CAPABILITY (0x19) and optionally check requirements\n"
2427"\n"
2528"SYNOPSIS\n"
2629" capability get\n"
27- " capability check [--need-pec on|off] [--min-speed 100|400] [--need-alert on|off] [--strict]\n"
30+ " capability check [--need-pec on|off] [--min-speed 100|400|1000]\n"
31+ " [--need-alert on|off] [--need-fp on|off] [--need-avsbus on|off]\n"
32+ " [--strict]\n"
2833"\n"
2934"DESCRIPTION (0x19 is a READ BYTE)\n"
3035" Bit 7 : PEC support (1 = device supports SMBus Packet Error Checking)\n"
31- " Bits 6:5: Max bus speed code (00=100 kHz, 01=400 kHz, 10/11 reserved)\n"
36+ " Bits 6:5: Max bus speed code (00=100 kHz, 01=400 kHz, 10=1 MHz, 11= reserved)\n"
3237" Bit 4 : SMBALERT# support (1 = device supports alert protocol/pin)\n"
33- " Bits 3:0: Reserved (should be 0)\n"
38+ " Bit 3 : Numeric format (0 = LINEAR/ULINEAR/DIRECT; 1 = IEEE-754 half-precision)\n"
39+ " Bit 2 : AVSBus support (1 = device supports AVSBus)\n"
40+ " Bits 1:0: Reserved (should be 0)\n"
3441"\n"
3542"OUTPUT (JSON) TBC\n"
3643" capability get ->\n"
3744" {\n"
3845" \"capability\": {\n"
3946" \"raw\": <byte>,\n"
4047" \"pec_supported\": true|false,\n"
41- " \"max_bus_speed\": { \"code\": 0|1|2|3, \"khz\": 100|400|null, \"text\": \"...\" },\n"
48+ " \"max_bus_speed\": { \"code\": 0|1|2|3, \"khz\": 100|400|1000| null, \"text\": \"...\" },\n"
4249" \"smbalert_supported\": true|false,\n"
43- " \"reserved_low_bits\": <0..15>\n"
50+ " \"numeric_format\": \"linear/direct\" | \"ieee754_half\",\n"
51+ " \"avsbus_supported\": true|false,\n"
52+ " \"reserved_low_bits\": <0..3>\n"
4453" }\n"
4554" }\n"
4655"\n"
4756" capability check -> adds\n"
48- " \"checks\": { \"pec_ok\": bool, \"bus_speed_ok\": bool, \"alert_ok\": bool, \"reserved_low_zero\": bool },\n"
57+ " \"checks\": {\n"
58+ " \"pec_ok\": bool, \"bus_speed_ok\": bool, \"alert_ok\": bool,\n"
59+ " \"numeric_format_ok\": bool, \"avsbus_ok\": bool,\n"
60+ " \"reserved_low_zero\": bool, \"speed_code_valid\": bool\n"
61+ " },\n"
4962" \"mismatches\": [ list of failed checks ]\n"
5063"\n"
5164"NOTES\n"
52- " * --strict also fails if reserved low bits (3 ..0) are non-zero.\n"
65+ " * --strict fails if reserved low bits (1 ..0) are non-zero and if speed code==3 (reserved) .\n"
5366" * This command intentionally does NOT include any MFR_* identity fields.\n"
5467"\n"
5568 );
@@ -68,24 +81,24 @@ speed_text(unsigned code, int *khz_out) {
6881 return "400 kHz" ;
6982 case 2 :
7083 if (khz_out )
71- * khz_out = -1 ;
72- return "reserved " ;
84+ * khz_out = 1000 ;
85+ return "1 MHz " ;
7386 case 3 :
87+ default :
7488 if (khz_out )
7589 * khz_out = -1 ;
7690 return "reserved" ;
7791 }
78- if (khz_out )
79- * khz_out = -1 ;
80- return "reserved" ;
8192}
8293
8394static void
8495decode_cap (uint8_t cap , json_t * dst ) {
8596 unsigned pec = (cap >> 7 ) & 0x1u ;
8697 unsigned spd = (cap >> 5 ) & 0x3u ;
8798 unsigned sal = (cap >> 4 ) & 0x1u ;
88- unsigned rsv = cap & 0x0Fu ;
99+ unsigned num = (cap >> 3 ) & 0x1u ;
100+ unsigned avs = (cap >> 2 ) & 0x1u ;
101+ unsigned rsv = cap & 0x03u ; /* only bits [1:0] are reserved */
89102
90103 int khz = -1 ;
91104 const char * txt = speed_text (spd , & khz );
@@ -95,16 +108,13 @@ decode_cap(uint8_t cap, json_t *dst) {
95108
96109 json_t * bs = json_object ();
97110 json_object_set_new (bs , "code" , json_integer (spd ));
98-
99- if (khz > 0 )
100- json_object_set_new (bs , "khz" , json_integer (khz ));
101- else
102- json_object_set_new (bs , "khz" , json_null ());
103-
111+ json_object_set_new (bs , "khz" , (khz > 0 ) ? json_integer (khz ) : json_null ());
104112 json_object_set_new (bs , "text" , json_string (txt ));
105113 json_object_set_new (dst , "max_bus_speed" , bs );
106114
107115 json_object_set_new (dst , "smbalert_supported" , json_boolean (sal ));
116+ json_object_set_new (dst , "numeric_format" , json_string (num ? "ieee754_half" : "linear/direct" ));
117+ json_object_set_new (dst , "avsbus_supported" , json_boolean (avs ));
108118 json_object_set_new (dst , "reserved_low_bits" , json_integer (rsv ));
109119}
110120
@@ -115,6 +125,23 @@ add_check(json_t *checks, const char *k, int ok, json_t *mism) {
115125 json_array_append_new (mism , json_string (k ));
116126}
117127
128+ static int
129+ parse_onoff (const char * s , int * out ) {
130+ if (!s || !out )
131+ return -1 ;
132+
133+ if (!strcmp (s , "on" ) || !strcmp (s , "yes" ) || !strcmp (s , "true" )) {
134+ * out = 1 ;
135+ return 0 ;
136+ }
137+ if (!strcmp (s , "off" ) || !strcmp (s , "no" ) || !strcmp (s , "false" )) {
138+ * out = 0 ;
139+ return 0 ;
140+ }
141+
142+ return -1 ;
143+ }
144+
118145int
119146cmd_capability (int fd , int argc , char * const * argv , int pretty ) {
120147 if (argc == 0 ) {
@@ -147,6 +174,7 @@ cmd_capability(int fd, int argc, char *const *argv, int pretty) {
147174 /* capability check [opts] */
148175 if (!strcmp (argv [0 ], "check" )) {
149176 const char * need_pec = NULL , * need_alert = NULL , * min_speed = NULL ;
177+ const char * need_fp = NULL , * need_avsbus = NULL ;
150178 int strict = 0 ;
151179
152180 for (int i = 1 ; i < argc ; i ++ ) {
@@ -156,6 +184,10 @@ cmd_capability(int fd, int argc, char *const *argv, int pretty) {
156184 need_alert = argv [++ i ];
157185 else if (!strcmp (argv [i ], "--min-speed" ) && i + 1 < argc )
158186 min_speed = argv [++ i ];
187+ else if (!strcmp (argv [i ], "--need-fp" ) && i + 1 < argc )
188+ need_fp = argv [++ i ];
189+ else if (!strcmp (argv [i ], "--need-avsbus" ) && i + 1 < argc )
190+ need_avsbus = argv [++ i ];
159191 else if (!strcmp (argv [i ], "--strict" ))
160192 strict = 1 ;
161193 else if (!strcmp (argv [i ], "--help" ) || !strcmp (argv [i ], "-h" )) {
@@ -181,14 +213,14 @@ cmd_capability(int fd, int argc, char *const *argv, int pretty) {
181213
182214 /* PEC check */
183215 if (need_pec ) {
184- int want = (! strcmp ( need_pec , "on" ) || ! strcmp ( need_pec , "yes" ) || ! strcmp ( need_pec , "true" ) );
185- int have = !!( cap & 0x80u );
186- add_check (checks , "pec_ok" , (want == have ), mism );
216+ int want , have = !!( cap & 0x80u );
217+ if ( parse_onoff ( need_pec , & want ) == 0 )
218+ add_check (checks , "pec_ok" , (want == have ), mism );
187219 }
188220
189221 /* Speed check */
190222 if (min_speed ) {
191- int req = atoi (min_speed ); /* expect 100 or 400 */
223+ int req = atoi (min_speed ); /* expect 100 or 400 or 1000 */
192224 unsigned code = (cap >> 5 ) & 0x3u ;
193225 int khz = -1 ;
194226 (void ) speed_text (code , & khz );
@@ -198,15 +230,30 @@ cmd_capability(int fd, int argc, char *const *argv, int pretty) {
198230
199231 /* ALERT check */
200232 if (need_alert ) {
201- int want = (!strcmp (need_alert , "on" ) || !strcmp (need_alert , "yes" ) || !strcmp (need_alert , "true" ));
202- int have = !!(cap & 0x10u );
203- add_check (checks , "alert_ok" , (want == have ), mism );
233+ int want , have = !!(cap & 0x10u );
234+ if (parse_onoff (need_alert , & want ) == 0 )
235+ add_check (checks , "alert_ok" , (want == have ), mism );
236+ }
237+
238+ /* Numeric format check (bit 3) */
239+ if (need_fp ) {
240+ int want_fp , have_fp = !!(cap & 0x08u );
241+ if (parse_onoff (need_fp , & want_fp ) == 0 )
242+ add_check (checks , "numeric_format_ok" , (want_fp == have_fp ), mism );
243+ }
244+
245+ /* AVSBus check (bit 2) */
246+ if (need_avsbus ) {
247+ int want_avs , have_avs = !!(cap & 0x04u );
248+ if (parse_onoff (need_avsbus , & want_avs ) == 0 )
249+ add_check (checks , "avsbus_ok" , (want_avs == have_avs ), mism );
204250 }
205251
206252 /* Reserved bits strictness */
207253 if (strict ) {
208- int rsv_ok = ((cap & 0x0Fu ) == 0 );
209- add_check (checks , "reserved_low_zero" , rsv_ok , mism );
254+ add_check (checks , "reserved_low_zero" , (cap & 0x03u ) == 0 , mism );
255+
256+ add_check (checks , "speed_code_valid" , ((cap >> 5 ) & 0x3u ) != 3u , mism );
210257 }
211258
212259 json_object_set_new (out , "checks" , checks );
0 commit comments