emcfanctloutputs.c revision 1.1 1 /* $NetBSD: emcfanctloutputs.c,v 1.1 2025/03/11 13:56:48 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.1 2025/03/11 13:56:48 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", res);
62 mj_append_field(&obj, "product_id", "integer", product_id);
63 mj_append_field(&obj, "product_family", "integer", 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", 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", i);
202 mj_append_field(&obj, "register_value", "integer", 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", human_value);
269 mj_append_field(&obj, "register", "integer", config_reg);
270 mj_append_field(&obj, "register_value", "integer", 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", human_value);
310 mj_append_field(&obj, "register", "integer", config_reg);
311 mj_append_field(&obj, "register_value", "integer", 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", res);
340 mj_append_field(&obj, "register", "integer", reg);
341 mj_append_field(&obj, "register_value", "integer", 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", the_fan+1);
388 mj_append_field(&obj, "pwm_base_frequency", "integer", fan_pwm_basefreq[tindex].human_int);
389 mj_append_field(&obj, "register", "integer", reg);
390 mj_append_field(&obj, "register_value", "integer", 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", the_fan+1);
431 mj_append_field(&obj, "inverted", "integer", inverted);
432 mj_append_field(&obj, "register", "integer", reg);
433 mj_append_field(&obj, "register_value", "integer", 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", the_fan+1);
469 mj_append_field(&obj, "pwm_output_type", "integer", pushpull);
470 mj_append_field(&obj, "register", "integer", reg);
471 mj_append_field(&obj, "register_value", "integer", 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", the_fan+1);
555 mj_append_field(&obj, "stalled", "integer", stalled);
556 mj_append_field(&obj, "spin_up_fail", "integer", spin_up_fail);
557 mj_append_field(&obj, "drive_fail", "integer", drive_fail);
558 mj_append_field(&obj, "register1", "integer", start_reg);
559 mj_append_field(&obj, "register1_value", "integer", res[0]);
560 mj_append_field(&obj, "register2", "integer", start_reg+1);
561 mj_append_field(&obj, "register2_value", "integer", res[1]);
562 mj_append_field(&obj, "register3", "integer", start_reg+2);
563 mj_append_field(&obj, "register3_value", "integer", res[2]);
564 mj_append_field(&obj, "register4", "integer", start_reg+3);
565 mj_append_field(&obj, "register4_value", "integer", 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", antiparalleldiode);
600 mj_append_field(&obj, "register", "integer", reg);
601 mj_append_field(&obj, "register_value", "integer", 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 smbusto = (res & smbus_timeout[tindex].clear_mask) ? true : false;
634
635 if (jsonify) {
636 memset(&obj, 0x0, sizeof(obj));
637 mj_create(&obj, "object");
638 mj_append_field(&obj, "smbus_timeout", "integer", smbusto);
639 mj_append_field(&obj, "register", "integer", reg);
640 mj_append_field(&obj, "register_value", "integer", res);
641 mj_asprint(&s, &obj, MJ_JSON_ENCODE);
642 printf("%s",s);
643 if (s != NULL)
644 free(s);
645 } else {
646 printf("SMBUS timeout:%s\n",(smbusto ? "Off" : "On"));
647 }
648
649 out:
650 return(err);
651 }
652
653