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