1 /* $NetBSD: emcfanctloutputs.c,v 1.2 2025/03/12 14:01:49 brad Exp $ */ 2 3 /* 4 * Copyright (c) 2025 Brad Spencer <brad (at) anduin.eldar.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #ifdef __RCSID 20 __RCSID("$NetBSD: emcfanctloutputs.c,v 1.2 2025/03/12 14:01:49 brad Exp $"); 21 #endif 22 23 #include <inttypes.h> 24 #include <stdbool.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <unistd.h> 28 #include <err.h> 29 #include <fcntl.h> 30 #include <string.h> 31 #include <limits.h> 32 #include <errno.h> 33 #include <mj.h> 34 35 #include <dev/i2c/emcfanreg.h> 36 #include <dev/i2c/emcfaninfo.h> 37 38 #define EXTERN 39 #include "emcfanctl.h" 40 #include "emcfanctlconst.h" 41 #include "emcfanctlutil.h" 42 #include "emcfanctloutputs.h" 43 44 int 45 output_emcfan_info(int fd, uint8_t product_id, int product_family, bool jsonify, bool debug) 46 { 47 int err = 0; 48 uint8_t res; 49 mj_t obj; 50 char *s = NULL; 51 char *pn; 52 char fn[8]; 53 54 err = emcfan_read_register(fd, EMCFAN_REVISION, &res, debug); 55 if (err != 0) 56 goto out; 57 58 if (jsonify) { 59 memset(&obj, 0x0, sizeof(obj)); 60 mj_create(&obj, "object"); 61 mj_append_field(&obj, "revision", "integer", (int64_t)res); 62 mj_append_field(&obj, "product_id", "integer", (int64_t)product_id); 63 mj_append_field(&obj, "product_family", "integer", (int64_t)product_family); 64 pn = emcfan_product_to_name(product_id); 65 mj_append_field(&obj, "chip_name", "string", pn, strlen(pn)); 66 emcfan_family_to_name(product_family, fn, sizeof(fn)); 67 mj_append_field(&obj, "family_name", "string", fn, strlen(fn)); 68 mj_asprint(&s, &obj, MJ_JSON_ENCODE); 69 printf("%s",s); 70 if (s != NULL) 71 free(s); 72 } else { 73 emcfan_family_to_name(product_family, fn, sizeof(fn)); 74 printf("Product Family: %s\n", fn); 75 printf("Chip name: %s\n", emcfan_product_to_name(product_id)); 76 printf("Revision: %d\n", res); 77 } 78 79 out: 80 return(err); 81 } 82 83 static void 84 output_emcfan_generic_reg_list(uint8_t product_id, const struct emcfan_registers the_registers[], long unsigned int the_registers_size, bool jsonify, bool debug) 85 { 86 mj_t array; 87 mj_t obj; 88 char *s = NULL; 89 int iindex; 90 91 iindex = emcfan_find_info(product_id); 92 if (iindex == -1) { 93 printf("Unknown info for product_id: %d\n",product_id); 94 exit(2); 95 } 96 97 if (debug) 98 fprintf(stderr, "output_emcfan_generic_reg_list: iindex=%d\n",iindex); 99 100 if (jsonify) { 101 memset(&array, 0x0, sizeof(array)); 102 mj_create(&array, "array"); 103 } 104 105 for(long unsigned int i = 0;i < the_registers_size;i++) { 106 if (emcfan_reg_is_real(iindex, the_registers[i].reg)) { 107 if (jsonify) { 108 memset(&obj, 0x0, sizeof(obj)); 109 mj_create(&obj, "object"); 110 mj_append_field(&obj, "register_name", "string", the_registers[i].name, strlen(the_registers[i].name)); 111 mj_append_field(&obj, "register", "integer", (int64_t)the_registers[i].reg); 112 mj_append(&array, "object", &obj); 113 mj_delete(&obj); 114 } else { 115 printf("%s\t%d\t0x%02X\n",the_registers[i].name,the_registers[i].reg,the_registers[i].reg); 116 } 117 } 118 } 119 120 if (jsonify) { 121 mj_asprint(&s, &array, MJ_JSON_ENCODE); 122 printf("%s",s); 123 if (s != NULL) 124 free(s); 125 mj_delete(&array); 126 } 127 } 128 129 void 130 output_emcfan_register_list(uint8_t product_id, int product_family, bool jsonify, bool debug) 131 { 132 if (debug) 133 fprintf(stderr,"output_emcfan_list: product_id=%d, product_family=%d\n",product_id, product_family); 134 135 switch(product_family) { 136 case EMCFAN_FAMILY_210X: 137 switch(product_id) { 138 case EMCFAN_PRODUCT_2101: 139 case EMCFAN_PRODUCT_2101R: 140 output_emcfan_generic_reg_list(product_id, emcfanctl_2101_registers, __arraycount(emcfanctl_2101_registers), jsonify, debug); 141 break; 142 case EMCFAN_PRODUCT_2103_1: 143 output_emcfan_generic_reg_list(product_id, emcfanctl_2103_1_registers, __arraycount(emcfanctl_2103_1_registers), jsonify, debug); 144 break; 145 case EMCFAN_PRODUCT_2103_24: 146 output_emcfan_generic_reg_list(product_id, emcfanctl_2103_24_registers, __arraycount(emcfanctl_2103_24_registers), jsonify, debug); 147 break; 148 case EMCFAN_PRODUCT_2104: 149 output_emcfan_generic_reg_list(product_id, emcfanctl_2104_registers, __arraycount(emcfanctl_2104_registers), jsonify, debug); 150 break; 151 case EMCFAN_PRODUCT_2106: 152 output_emcfan_generic_reg_list(product_id, emcfanctl_2106_registers, __arraycount(emcfanctl_2106_registers), jsonify, debug); 153 break; 154 default: 155 printf("UNSUPPORTED YET %d\n",product_id); 156 exit(99); 157 break; 158 }; 159 break; 160 case EMCFAN_FAMILY_230X: 161 output_emcfan_generic_reg_list(product_id, emcfanctl_230x_registers, __arraycount(emcfanctl_230x_registers), jsonify, debug); 162 break; 163 }; 164 } 165 166 static int 167 output_emcfan_230x_read_reg(int fd, uint8_t product_id, int product_family, uint8_t start, uint8_t end, bool jsonify, bool debug) 168 { 169 int err = 0; 170 uint8_t res; 171 mj_t array; 172 mj_t obj; 173 char *s = NULL; 174 int iindex; 175 const char *rn; 176 177 iindex = emcfan_find_info(product_id); 178 if (iindex == -1) { 179 printf("Unknown info for product_id: %d\n",product_id); 180 exit(2); 181 } 182 183 if (debug) 184 fprintf(stderr, "output_emcfan_230x_read_reg: product_id=%d, product_family=%d, iindex=%d\n",product_id, product_family, iindex); 185 186 if (jsonify) { 187 memset(&array, 0x0, sizeof(array)); 188 mj_create(&array, "array"); 189 } 190 191 for(int i = start; i <= end; i++) { 192 if (emcfan_reg_is_real(iindex, i)) { 193 err = emcfan_read_register(fd, i, &res, debug); 194 if (err != 0) 195 break; 196 if (jsonify) { 197 memset(&obj, 0x0, sizeof(obj)); 198 mj_create(&obj, "object"); 199 rn = emcfan_regname_by_reg(product_id, product_family, i); 200 mj_append_field(&obj, "register_name", "string", rn, strlen(rn)); 201 mj_append_field(&obj, "register", "integer", (int64_t)i); 202 mj_append_field(&obj, "register_value", "integer", (int64_t)res); 203 mj_append(&array, "object", &obj); 204 mj_delete(&obj); 205 } else { 206 printf("%s;%d (0x%02X);%d (0x%02X)\n",emcfan_regname_by_reg(product_id, product_family, i),i,i,res,res); 207 } 208 } 209 } 210 211 if (jsonify) { 212 mj_asprint(&s, &array, MJ_JSON_ENCODE); 213 printf("%s",s); 214 if (s != NULL) 215 free(s); 216 mj_delete(&array); 217 } 218 219 return(err); 220 } 221 222 int 223 output_emcfan_register_read(int fd, uint8_t product_id, int product_family, uint8_t start, uint8_t end, bool jsonify, bool debug) 224 { 225 int err = 0; 226 227 if (debug) 228 fprintf(stderr,"output_emcfan_register_read: start=%d 0x%02X, end=%d 0x%02X\n",start, start, end, end); 229 230 switch(product_family) { 231 case EMCFAN_FAMILY_210X: 232 err = output_emcfan_230x_read_reg(fd, product_id, product_family, start, end, jsonify, debug); 233 break; 234 case EMCFAN_FAMILY_230X: 235 err = output_emcfan_230x_read_reg(fd, product_id, product_family, start, end, jsonify, debug); 236 break; 237 }; 238 239 return(err); 240 } 241 242 int 243 output_emcfan_minexpected_rpm(int fd, uint8_t product_id, int product_family, uint8_t config_reg, bool jsonify, bool debug) 244 { 245 int err = 0; 246 uint8_t raw_res, res; 247 uint8_t clear_mask; 248 int human_value; 249 char *s = NULL; 250 mj_t obj; 251 252 err = emcfan_read_register(fd, config_reg, &raw_res, debug); 253 if (err != 0) 254 goto out; 255 256 clear_mask = fan_minexpectedrpm[0].clear_mask; 257 res = raw_res & clear_mask; 258 if (debug) 259 fprintf(stderr,"%s: clear_mask=0x%02X 0x%02X, raw_res=%d (0x%02X), res=%d (0x%02X)\n",__func__,clear_mask,(uint8_t)~clear_mask,raw_res,raw_res,res,res); 260 human_value = find_human_int(fan_minexpectedrpm, __arraycount(fan_minexpectedrpm), res); 261 262 if (human_value == -10191) 263 return(EINVAL); 264 265 if (jsonify) { 266 memset(&obj, 0x0, sizeof(obj)); 267 mj_create(&obj, "object"); 268 mj_append_field(&obj, "minimum_expected_rpm", "integer", (int64_t)human_value); 269 mj_append_field(&obj, "register", "integer", (int64_t)config_reg); 270 mj_append_field(&obj, "register_value", "integer", (int64_t)raw_res); 271 mj_asprint(&s, &obj, MJ_JSON_ENCODE); 272 printf("%s",s); 273 if (s != NULL) 274 free(s); 275 } else { 276 printf("Minumum expected rpm:%d\n",human_value); 277 } 278 279 out: 280 return(err); 281 } 282 283 int 284 output_emcfan_edges(int fd, uint8_t product_id, int product_family, uint8_t config_reg, bool jsonify, bool debug) 285 { 286 int err = 0; 287 uint8_t raw_res, res; 288 uint8_t clear_mask; 289 int human_value; 290 char *s = NULL; 291 mj_t obj; 292 293 err = emcfan_read_register(fd, config_reg, &raw_res, debug); 294 if (err != 0) 295 goto out; 296 297 clear_mask = fan_numedges[0].clear_mask; 298 res = raw_res & clear_mask; 299 if (debug) 300 fprintf(stderr,"%s: clear_mask=0x%02X 0x%02X, raw_res=%d (0x%02X), res=%d (0x%02X)\n",__func__,clear_mask,(uint8_t)~clear_mask,raw_res,raw_res,res,res); 301 human_value = find_human_int(fan_numedges, __arraycount(fan_numedges), res); 302 303 if (human_value == -10191) 304 return(EINVAL); 305 306 if (jsonify) { 307 memset(&obj, 0x0, sizeof(obj)); 308 mj_create(&obj, "object"); 309 mj_append_field(&obj, "num_edges", "integer", (int64_t)human_value); 310 mj_append_field(&obj, "register", "integer", (int64_t)config_reg); 311 mj_append_field(&obj, "register_value", "integer", (int64_t)raw_res); 312 mj_asprint(&s, &obj, MJ_JSON_ENCODE); 313 printf("%s",s); 314 if (s != NULL) 315 free(s); 316 } else { 317 printf("Number of edges:%d\n",human_value); 318 } 319 320 out: 321 return(err); 322 } 323 324 static int 325 output_emcfan_simple_int(int fd, uint8_t product_id, int product_family, uint8_t reg, const char *what, const char *whatj, bool jsonify, bool debug) 326 { 327 int err = 0; 328 uint8_t res; 329 char *s = NULL; 330 mj_t obj; 331 332 err = emcfan_read_register(fd, reg, &res, debug); 333 if (err != 0) 334 goto out; 335 336 if (jsonify) { 337 memset(&obj, 0x0, sizeof(obj)); 338 mj_create(&obj, "object"); 339 mj_append_field(&obj, whatj, "integer", (int64_t)res); 340 mj_append_field(&obj, "register", "integer", (int64_t)reg); 341 mj_append_field(&obj, "register_value", "integer",(int64_t) res); 342 mj_asprint(&s, &obj, MJ_JSON_ENCODE); 343 printf("%s",s); 344 if (s != NULL) 345 free(s); 346 } else { 347 printf("%s:%d\n",what, res); 348 } 349 350 out: 351 return(err); 352 } 353 354 int 355 output_emcfan_drive(int fd, uint8_t product_id, int product_family, uint8_t reg, bool jsonify, bool debug) 356 { 357 return(output_emcfan_simple_int(fd, product_id, product_family, reg, "Drive", "drive_level", jsonify, debug)); 358 } 359 360 int 361 output_emcfan_divider(int fd, uint8_t product_id, int product_family, uint8_t reg, bool jsonify, bool debug) 362 { 363 return(output_emcfan_simple_int(fd, product_id, product_family, reg, "Divider", "frequency_divider", jsonify, debug)); 364 } 365 366 int 367 output_emcfan_pwm_basefreq(int fd, uint8_t product_id, int product_family, uint8_t reg, int the_fan, bool jsonify, bool debug) 368 { 369 int err = 0; 370 uint8_t res; 371 int tindex; 372 char *s = NULL; 373 mj_t obj; 374 375 err = emcfan_read_register(fd, reg, &res, debug); 376 if (err != 0) 377 goto out; 378 379 tindex = find_translated_blob_by_bits_instance(fan_pwm_basefreq, __arraycount(fan_pwm_basefreq), res, the_fan); 380 381 if (debug) 382 fprintf(stderr,"%s: reg=%d 0x%02X, res=0x%02x, tindex=%d, the_fan=%d\n",__func__,reg,reg,res,tindex,the_fan); 383 384 if (jsonify) { 385 memset(&obj, 0x0, sizeof(obj)); 386 mj_create(&obj, "object"); 387 mj_append_field(&obj, "fan", "integer", (int64_t)the_fan+1); 388 mj_append_field(&obj, "pwm_base_frequency", "integer", (int64_t)fan_pwm_basefreq[tindex].human_int); 389 mj_append_field(&obj, "register", "integer", (int64_t)reg); 390 mj_append_field(&obj, "register_value", "integer", (int64_t)res); 391 mj_asprint(&s, &obj, MJ_JSON_ENCODE); 392 printf("%s",s); 393 if (s != NULL) 394 free(s); 395 } else { 396 printf("PWM Base Frequency:%d\n",fan_pwm_basefreq[tindex].human_int); 397 } 398 399 out: 400 return(err); 401 } 402 403 int 404 output_emcfan_polarity(int fd, uint8_t product_id, int product_family, uint8_t reg, int the_fan, bool jsonify, bool debug) 405 { 406 int err = 0; 407 uint8_t res; 408 int mask; 409 bool inverted = false; 410 char *s = NULL; 411 mj_t obj; 412 413 err = emcfan_read_register(fd, reg, &res, debug); 414 if (err != 0) 415 goto out; 416 417 if (product_id == EMCFAN_PRODUCT_2101 || 418 product_id == EMCFAN_PRODUCT_2101R) { 419 mask = 0x10; 420 } else { 421 mask = 1 << the_fan; 422 } 423 424 if (res & mask) 425 inverted = true; 426 427 if (jsonify) { 428 memset(&obj, 0x0, sizeof(obj)); 429 mj_create(&obj, "object"); 430 mj_append_field(&obj, "fan", "integer", (int64_t)the_fan+1); 431 mj_append_field(&obj, "inverted", "integer", (int64_t)inverted); 432 mj_append_field(&obj, "register", "integer", (int64_t)reg); 433 mj_append_field(&obj, "register_value", "integer", (int64_t)res); 434 mj_asprint(&s, &obj, MJ_JSON_ENCODE); 435 printf("%s",s); 436 if (s != NULL) 437 free(s); 438 } else { 439 printf("Inverted:%s\n",(inverted ? "Yes" : "No")); 440 } 441 442 out: 443 return(err); 444 } 445 446 int 447 output_emcfan_pwm_output_type(int fd, uint8_t product_id, int product_family, uint8_t reg, int the_fan, bool jsonify, bool debug) 448 { 449 int err = 0; 450 uint8_t res; 451 int mask; 452 bool pushpull = false; 453 char *s = NULL; 454 mj_t obj; 455 456 err = emcfan_read_register(fd, reg, &res, debug); 457 if (err != 0) 458 goto out; 459 460 mask = 1 << the_fan; 461 462 if (res & mask) 463 pushpull= true; 464 465 if (jsonify) { 466 memset(&obj, 0x0, sizeof(obj)); 467 mj_create(&obj, "object"); 468 mj_append_field(&obj, "fan", "integer", (int64_t)the_fan+1); 469 mj_append_field(&obj, "pwm_output_type", "integer", (int64_t)pushpull); 470 mj_append_field(&obj, "register", "integer", (int64_t)reg); 471 mj_append_field(&obj, "register_value", "integer", (int64_t)res); 472 mj_asprint(&s, &obj, MJ_JSON_ENCODE); 473 printf("%s",s); 474 if (s != NULL) 475 free(s); 476 } else { 477 printf("PWM Output Type:%s\n",(pushpull ? "push-pull" : "open drain")); 478 } 479 480 out: 481 return(err); 482 } 483 484 int 485 output_emcfan_fan_status(int fd, uint8_t product_id, int product_family, uint8_t start_reg, uint8_t end_reg, int the_fan, bool jsonify, bool debug) 486 { 487 int err = 0; 488 uint8_t res[4]; 489 bool stalled = false; 490 bool spin_up_fail = false; 491 bool drive_fail = false; 492 uint8_t stall_mask = 0; 493 uint8_t spin_mask = 0; 494 uint8_t drive_mask = 0; 495 char *s = NULL; 496 mj_t obj; 497 498 res[0] = res[1] = res[2] = res[3] = 0; 499 500 if (product_family == EMCFAN_FAMILY_210X) { 501 err = emcfan_read_register(fd, start_reg, &res[0], debug); 502 if (err != 0) 503 goto out; 504 err = emcfan_read_register(fd, start_reg, &res[0], debug); 505 if (err != 0) 506 goto out; 507 508 switch(the_fan) { 509 case 0: 510 stall_mask = 0b00000001; 511 spin_mask = 0b00000010; 512 drive_mask = 0b00100000; 513 break; 514 case 1: 515 stall_mask = 0b00000100; 516 spin_mask = 0b00001000; 517 drive_mask = 0b01000000; 518 break; 519 default: 520 fprintf(stderr,"No status for fan: %d\n", the_fan + 1); 521 err = EINVAL; 522 }; 523 if (debug) 524 fprintf(stderr,"%s: product_family=%d, stall_mask=0x%02X, spin_mask=0x%02X, drive_mask=0x%02X, res=0x%02X\n",__func__, 525 product_family, stall_mask, spin_mask, drive_mask, res[0]); 526 stalled = (res[0] & stall_mask); 527 spin_up_fail = (res[0] & spin_mask); 528 drive_fail = (res[0] & drive_mask); 529 } else { 530 int j = 0; 531 for(uint8_t i = start_reg; i <= end_reg;i++,j++) { 532 err = emcfan_read_register(fd, i, &res[j], debug); 533 if (err != 0) 534 goto out; 535 } 536 j = 0; 537 for(uint8_t i = start_reg; i <= end_reg;i++,j++) { 538 err = emcfan_read_register(fd, i, &res[j], debug); 539 if (err != 0) 540 goto out; 541 } 542 543 if (debug) 544 fprintf(stderr,"%s: product_family=%d, res[0]=0x%02X, res[1]=0x%02X, res[2]=0x%02X, res[3]=0x%02X\n", 545 __func__, product_family, res[0], res[1], res[2], res[3]); 546 stalled = (res[1] & (1 << the_fan)); 547 spin_up_fail = (res[2] & (1 << the_fan)); 548 drive_fail = (res[3] & (1 << the_fan)); 549 } 550 551 if (jsonify) { 552 memset(&obj, 0x0, sizeof(obj)); 553 mj_create(&obj, "object"); 554 mj_append_field(&obj, "fan", "integer", (int64_t)the_fan+1); 555 mj_append_field(&obj, "stalled", "integer", (int64_t)stalled); 556 mj_append_field(&obj, "spin_up_fail", "integer", (int64_t)spin_up_fail); 557 mj_append_field(&obj, "drive_fail", "integer", (int64_t)drive_fail); 558 mj_append_field(&obj, "register1", "integer", (int64_t)start_reg); 559 mj_append_field(&obj, "register1_value", "integer", (int64_t)res[0]); 560 mj_append_field(&obj, "register2", "integer", (int64_t)start_reg+1); 561 mj_append_field(&obj, "register2_value", "integer", (int64_t)res[1]); 562 mj_append_field(&obj, "register3", "integer", (int64_t)start_reg+2); 563 mj_append_field(&obj, "register3_value", "integer", (int64_t)res[2]); 564 mj_append_field(&obj, "register4", "integer", (int64_t)start_reg+3); 565 mj_append_field(&obj, "register4_value", "integer", (int64_t)res[3]); 566 mj_asprint(&s, &obj, MJ_JSON_ENCODE); 567 printf("%s",s); 568 if (s != NULL) 569 free(s); 570 } else { 571 printf("Stalled: %s\n",stalled ? "Yes" : "No"); 572 printf("Spin up failed: %s\n",spin_up_fail ? "Yes" : "No"); 573 printf("Drive failed: %s\n",drive_fail ? "Yes" : "No"); 574 } 575 576 out: 577 return(err); 578 } 579 580 int 581 output_emcfan_apd(int fd, uint8_t product_id, int product_family, uint8_t reg, bool jsonify, bool debug) 582 { 583 int err = 0; 584 uint8_t res; 585 bool antiparalleldiode = false; 586 char *s = NULL; 587 mj_t obj; 588 589 err = emcfan_read_register(fd, reg, &res, debug); 590 if (err != 0) 591 goto out; 592 593 if (res & 0x01) 594 antiparalleldiode = true; 595 596 if (jsonify) { 597 memset(&obj, 0x0, sizeof(obj)); 598 mj_create(&obj, "object"); 599 mj_append_field(&obj, "apd", "integer", (int64_t)antiparalleldiode); 600 mj_append_field(&obj, "register", "integer", (int64_t)reg); 601 mj_append_field(&obj, "register_value", "integer", (int64_t)res); 602 mj_asprint(&s, &obj, MJ_JSON_ENCODE); 603 printf("%s",s); 604 if (s != NULL) 605 free(s); 606 } else { 607 printf("APD:%s\n",(antiparalleldiode ? "On" : "Off")); 608 } 609 610 out: 611 return(err); 612 } 613 614 int 615 output_emcfan_smbusto(int fd, uint8_t product_id, int product_family, uint8_t reg, int instance, bool jsonify, bool debug) 616 { 617 int err = 0; 618 uint8_t res; 619 int tindex; 620 bool smbusto = false; 621 char *s = NULL; 622 mj_t obj; 623 624 err = emcfan_read_register(fd, reg, &res, debug); 625 if (err != 0) 626 goto out; 627 628 tindex = find_translated_blob_by_bits_instance(smbus_timeout, __arraycount(smbus_timeout), res, instance); 629 630 if (debug) 631 fprintf(stderr,"%s: reg=%d 0x%02X, res=0x%02x, tindex=%d, instance=%d\n",__func__,reg,reg,res,tindex,instance); 632 633 /* The logic is inverted for the timeout */ 634 smbusto = (res & smbus_timeout[tindex].clear_mask) ? false : true; 635 636 if (jsonify) { 637 memset(&obj, 0x0, sizeof(obj)); 638 mj_create(&obj, "object"); 639 mj_append_field(&obj, "smbus_timeout", "integer", (int64_t)smbusto); 640 mj_append_field(&obj, "register", "integer", (int64_t)reg); 641 mj_append_field(&obj, "register_value", "integer", (int64_t)res); 642 mj_asprint(&s, &obj, MJ_JSON_ENCODE); 643 printf("%s",s); 644 if (s != NULL) 645 free(s); 646 } else { 647 printf("SMBUS timeout:%s\n",(smbusto ? "On" : "Off")); 648 } 649 650 out: 651 return(err); 652 } 653 654