4 * A cable tester program for apcupsd.
6 * Hacked from apcupsd.c by Kern Sibbald, Sept 2000
10 * Copyright (C) 2000-2004 Kern Sibbald
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of version 2 of the GNU General
14 * Public License as published by the Free Software Foundation.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
21 * You should have received a copy of the GNU General Public
22 * License along with this program; if not, write to the Free
23 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
33 int le_bit
= TIOCM_LE
;
34 int st_bit
= TIOCM_ST
;
35 int sr_bit
= TIOCM_SR
;
36 int dtr_bit
= TIOCM_DTR
;
37 int rts_bit
= TIOCM_RTS
;
38 int cts_bit
= TIOCM_CTS
;
39 int cd_bit
= TIOCM_CD
;
40 int rng_bit
= TIOCM_RNG
;
41 int dsr_bit
= TIOCM_DSR
;
43 struct termios oldtio
;
44 struct termios newtio
;
46 /* Forward referenced functions */
47 static void do_dumb_testing(void);
48 static void test1(void);
49 static void test2(void);
50 static void test3(void);
51 static void test4(void);
52 static void test5(void);
53 static void test6(void);
54 static void guess(void);
56 static void do_smart_testing(void);
58 #ifdef HAVE_APCSMART_DRIVER
59 static void smart_test1(void);
60 static void smart_calibration(void);
61 static void monitor_calibration_progress(int monitor
);
62 static void terminate_calibration(int ask
);
63 static void program_smart_eeprom(void);
64 static void print_eeprom_values(UPSINFO
*ups
);
65 static void smart_ttymode(void);
66 static void parse_eeprom_cmds(char *eprom
, char locale
);
67 int apcsmart_ups_program_eeprom(UPSINFO
*ups
, int command
, const char *data
);
68 static void print_valid_eeprom_values(UPSINFO
*ups
);
71 static void do_usb_testing(void);
73 #ifdef HAVE_USB_DRIVER
75 /* USB driver functions */
76 #include "drivers/usb/usb.h"
78 /* Our own test functions */
79 static void usb_kill_power_test(void);
80 static void usb_get_self_test_result(void);
81 static void usb_run_self_test(void);
82 static int usb_get_battery_date(void);
83 static void usb_set_battery_date(void);
84 static void usb_get_manf_date(void);
85 static void usb_set_alarm(void);
86 static void usb_set_sens(void);
87 static void usb_set_xferv(int lowhigh
);
88 static void usb_calibration();
89 static void usb_test_alarm(void);
90 static int usb_get_self_test_interval(void);
91 static void usb_set_self_test_interval(void);
94 static void strip_trailing_junk(char *cmd
);
95 static char *get_cmd(const char *prompt
);
96 static int write_file(char *buf
);
99 /* Static variables */
100 static int normal
, no_cable
, no_power
, low_batt
;
101 static int test1_done
= 0;
102 static int test2_done
= 0;
103 static int test3_done
= 0;
104 static int test4_done
= 0;
105 static int test5_done
= 0;
108 /* Print a message, and also write it to an output file */
109 static void pmsg(const char *fmt
, ...)
114 va_start(arg_ptr
, fmt
);
115 avsnprintf(buf
, sizeof(buf
), (char *)fmt
, arg_ptr
);
122 /* Write output into "log" file */
123 static int write_file(char *buf
)
125 static int out_fd
= -1;
128 out_fd
= open("apctest.output", O_WRONLY
| O_CREAT
| O_APPEND
, 0644);
130 printf("Could not create apctest.output: %s\n", strerror(errno
));
134 return write(out_fd
, buf
, strlen(buf
));
137 /* Print out current time */
138 static void ptime(void)
141 time_t now
= time(NULL
);
143 strftime(dt
, MAXSTRING
, "%Y-%m-%d %T ", localtime(&now
));
149 * The terminate function; trapping signals allows apctest
150 * to exit and cleanly close logfiles, and reset the tty back
151 * to its original settings. You may want to add this
152 * to all configurations. Of course, the file descriptors
153 * must be global for this to work, I also set them to
154 * NULL initially to allow terminate to determine whether
155 * it should close them.
157 void apctest_terminate(int sig
)
161 pmsg("apctest exiting, signal %u\n", sig
);
168 delete_lockfile(ups
);
177 void apctest_error_cleanup(UPSINFO
*ups
)
180 delete_lockfile(ups
);
182 pmsg("apctest error termination completed\n");
189 * Subroutine error_out prints FATAL ERROR with file,
190 * line number, and the error message then cleans up
191 * and exits. It is normally called from the Error_abort
192 * define, which inserts the file and line number.
194 void apctest_error_out(const char *file
, int line
, const char *fmt
, ...)
200 asnprintf(buf
, sizeof(buf
),
201 "apctest FATAL ERROR in %s at line %d\n", file
, line
);
204 va_start(arg_ptr
, fmt
);
205 avsnprintf((char *)&buf
[i
], sizeof(buf
) - i
, (char *)fmt
, arg_ptr
);
210 apctest_error_cleanup(core_ups
); /* finish the work */
214 * Subroutine error_exit simply prints the supplied error
215 * message, cleans up, and exits.
217 void apctest_error_exit(const char *fmt
, ...)
222 va_start(arg_ptr
, fmt
);
223 avsnprintf(buf
, sizeof(buf
), (char *)fmt
, arg_ptr
);
228 apctest_error_cleanup(core_ups
); /* finish the work */
234 /* This application must be linked as console app. */
236 int main(int argc
, char *argv
[])
238 /* Set specific error_* handlers. */
239 error_out
= apctest_error_out
;
240 error_exit
= apctest_error_exit
;
243 * Default config file. If we set a config file in startup switches, it
244 * will be re-filled by parse_options()
248 ups
= new_ups(); /* get new ups */
250 Error_abort1("%s: init_ipc failed.\n", argv
[0]);
252 init_ups_struct(ups
);
253 core_ups
= ups
; /* this is our core ups structure */
255 /* parse_options is self messaging on errors, so we need only to exit() */
256 if (parse_options(argc
, argv
))
261 pmsg("apctest " APCUPSD_RELEASE
" (" ADATE
") " APCUPSD_HOST
"\n");
263 pmsg("Checking configuration ...\n");
264 check_for_config(ups
, cfgfile
);
267 if (ups
->driver
== NULL
)
268 Error_abort0("apctest cannot continue without a valid driver.\n");
270 pmsg("Attached to driver: %s\n", ups
->driver
->driver_name
);
272 ups
->start_time
= time(NULL
);
274 /* Print configuration */
275 pmsg("sharenet.type = %s\n", ups
->sharenet
.long_name
);
276 pmsg("cable.type = %s\n", ups
->cable
.long_name
);
277 pmsg("mode.type = %s\n", ups
->mode
.long_name
);
279 delete_lockfile(ups
);
281 pmsg("Setting up the port ...\n");
285 pmsg("apctest: bad option, I cannot do a killpower\n");
286 apctest_terminate(0);
289 init_signals(apctest_terminate
);
291 pmsg("Doing prep_device() ...\n");
295 * This isn't a documented option but can be used
296 * for testing dumb mode on a SmartUPS if you have
299 if (dumb_mode_test
) {
300 #ifdef HAVE_APCSMART_DRIVER
303 write(ups
->fd
, "R", 1); /* enter dumb mode */
305 getline(ans
, sizeof(ans
), ups
);
306 pmsg("Going dumb: %s\n", ans
);
308 pmsg("apcsmart not compiled: dumb mode test unavailable\n");
312 switch (ups
->mode
.type
)
315 pmsg("\nYou are using a USB cable type, so I'm entering USB test mode\n");
319 pmsg("\nYou are using a SMART cable type, so I'm entering SMART test mode\n");
323 pmsg("\nYou are using a DUMB cable type, so I'm entering DUMB test mode\n");
327 pmsg("Testing not yet implemented for this UPSTYPE.\n");
329 apctest_terminate(0);
330 return -1; /* to keep compiler happy */
333 static void print_bits(int bits
)
337 asnprintf(buf
, sizeof(buf
), "IOCTL GET: %x ", bits
);
340 astrncat(buf
, "LE ", sizeof(buf
));
342 astrncat(buf
, "ST ", sizeof(buf
));
344 astrncat(buf
, "SR ", sizeof(buf
));
346 astrncat(buf
, "DTR ", sizeof(buf
));
348 astrncat(buf
, "RTS ", sizeof(buf
));
350 astrncat(buf
, "CTS ", sizeof(buf
));
352 astrncat(buf
, "CD ", sizeof(buf
));
354 astrncat(buf
, "RNG ", sizeof(buf
));
356 astrncat(buf
, "DSR ", sizeof(buf
));
358 astrncat(buf
, "\n", sizeof(buf
));
363 static void do_dumb_testing(void)
368 pmsg("Hello, this is the apcupsd Cable Test program.\n\n"
369 "We are beginning testing for dumb UPSes, which\n"
370 "use signaling rather than commands.\n"
371 "Most tests enter a loop polling every second for 10 seconds.\n");
375 "1) Test 1 - normal mode\n"
376 "2) Test 2 - no cable\n"
377 "3) Test 3 - no power\n"
378 "4) Test 4 - low battery (requires test 3 first)\n"
379 "5) Test 5 - battery exhausted\n"
380 "6) Test 6 - kill UPS power\n"
381 "7) Test 7 - run tests 1 through 5\n"
382 "8) Guess which is the appropriate cable\n"
385 cmd
= get_cmd("Select test number: ");
388 int item
= atoi(cmd
);
420 if (tolower(*cmd
) == 'q')
423 pmsg("Illegal response. Please enter 1-8,Q\n");
427 pmsg("Illegal response. Please enter 1-8,Q\n");
432 pmsg("End apctest.\n");
436 * Poll 10 times once per second and report any
437 * change in serial port bits.
439 static int test_bits(int inbits
)
444 for (i
= 0; i
< 10; i
++) {
445 if (ioctl(ups
->fd
, TIOCMGET
, &nbits
) < 0) {
446 pmsg("ioctl error, big problem: %s\n", strerror(errno
));
450 if (i
== 0 || nbits
!= bits
) {
462 static void test1(void)
464 pmsg("\nFor the first test, everything should be normal.\n"
465 "The UPS should be plugged in to the power, and the serial cable\n"
466 "should be connected to the computer.\n\n"
467 "Please enter any character when ready to continue: ");
471 normal
= test_bits(0);
474 pmsg("Test 1: normal condition, completed.\n");
478 static void test2(void)
480 pmsg("\nFor the second test, the UPS should be plugged in to the power, \n"
481 "but the serial port should be DISCONNECTED from the computer.\n\n"
482 "Please enter any character when ready to continue: ");
486 no_cable
= test_bits(0);
489 pmsg("Test 2: no cable, completed. \n");
493 static void test3(void)
495 pmsg("\nFor the third test, the serial cable should be plugged\n"
496 "back into the UPS, but the AC power plug to the UPS should be DISCONNECTED.\n\n"
497 "Please enter any character when ready to continue: ");
501 no_power
= test_bits(0);
504 pmsg("Test 3: no power, completed.\n");
508 static void test4(void)
513 pmsg("We need the output of test 3 to run this test.\n"
514 "Please run test 3 first then this test.\n");
518 pmsg("\nThe fourth test is the same as the third test:\n"
519 "the serial cable should be plugged in to the UPS, but the AC power\n"
520 "plug to the UPS should be DISCONNECTED. In addition, you should\n"
521 "continue this test until the batteries are exhausted.\n"
522 "If apctest detects a state change, it will stop\n"
523 "the test. If not, hit control-C to stop the program\n\n"
524 "PLEASE DO NOT RUN THIS TEST WITH A COMPUTER CONNECTED TO YOUR UPS!!!\n\n"
525 "Please enter any character when ready to continue: ");
532 pmsg("Start test 4: ");
535 /* Spin until we get a state change */
537 if (ioctl(ups
->fd
, TIOCMGET
, &bits
) < 0) {
538 pmsg("ioctl error, big problem: %s\n", strerror(errno
));
542 if (bits
!= low_batt
) {
556 pmsg("Test 4: low battery, completed.\n");
560 static void test5(void)
562 int i
, bits
, last_bits
= 0;
564 pmsg("\nThe fifth test is the same as the third test:\n"
565 "the serial cable should be plugged in to the UPS, but the AC power\n"
566 "plug to the UPS should be DISCONNECTED. In addition, you should\n"
567 "continue this test until the batteries are exhausted.\n"
568 "If apctest detects a state change, contrary to test 4, it\n"
569 "will not stop. The idea is to see ANY changed bits just up to\n"
570 "the very moment that the UPS powers down.\n\n"
571 "PLEASE DO NOT RUN THIS TEST WITH A COMPUTER CONNECTED TO YOUR UPS!!!\n\n"
572 "Please enter any character when ready to continue: ");
576 pmsg("Start test 5:\n");
578 /* Spin until we get a state change */
580 if (ioctl(ups
->fd
, TIOCMGET
, &bits
) < 0) {
581 pmsg("ioctl error, big problem: %s\n", strerror(errno
));
586 i
= 0; /* force print once a minute */
588 if (i
== 0 || bits
!= last_bits
) {
597 /* Should never get here */
600 pmsg("Test 5: battery exhausted, completed.\n");
604 static void test6(void)
608 pmsg("\nThis test will attempt to power down the UPS.\n"
609 "The serial cable should be plugged in to the UPS, but the\n"
610 "AC power plug to the UPS should be DISCONNECTED.\n\n"
611 "PLEASE DO NOT RUN THIS TEST WITH A COMPUTER CONNECTED TO YOUR UPS!!!\n\n"
612 "Please enter any character when ready to continue: ");
616 if (ioctl(ups
->fd
, TIOCMGET
, &bits
) < 0) {
617 pmsg("ioctl error, big problem: %s\n", strerror(errno
));
623 make_file(ups
, ups
->pwrfailpath
);
624 initiate_hibernate(ups
);
625 unlink(ups
->pwrfailpath
);
628 pmsg("returned from kill_power function.\n");
630 if (ioctl(ups
->fd
, TIOCMGET
, &bits
) < 0) {
631 pmsg("ioctl error, big problem: %s\n", strerror(errno
));
640 * Make a wild guess at the cable type
642 * If I had more data on each of the cable types, this could
645 static void guess(void)
649 if (!(test1_done
&& test3_done
)) {
650 pmsg("Test 1 and test 3 must be performed before I can make a guess.\n");
653 if (!(normal
& (cd_bit
| cts_bit
)) && (no_power
& cd_bit
) && (low_batt
& cts_bit
)) {
654 pmsg("This looks like a CUSTOM_SIMPLE cable\n");
658 if (!(normal
& (cd_bit
| cts_bit
)) && (no_power
& cts_bit
) && (low_batt
& cd_bit
)) {
659 pmsg("This looks like a 940-0020A\n");
663 if (!(normal
& (cd_bit
| sr_bit
)) && (no_power
& cd_bit
) && (low_batt
& sr_bit
)) {
664 pmsg("This looks like a 940-0023A cable\n");
668 if (!(normal
& (rng_bit
| cd_bit
)) && (no_power
& rng_bit
) && (low_batt
& cd_bit
)) {
669 pmsg("This looks like a 940-0095A cable\n");
674 pmsg("Hmmm. I don't quite know what you have. Sorry.\n");
678 static void do_smart_testing(void)
680 #ifdef HAVE_APCSMART_DRIVER
684 pmsg("Hello, this is the apcupsd Cable Test program.\n"
685 "This part of apctest is for testing Smart UPSes.\n"
686 "Please select the function you want to perform.\n");
690 "1) Query the UPS for all known values\n"
691 "2) Perform a Battery Runtime Calibration\n"
692 "3) Abort Battery Calibration\n"
693 "4) Monitor Battery Calibration progress\n"
694 "5) Program EEPROM\n"
695 "6) Enter TTY mode communicating with UPS\n"
698 cmd
= get_cmd("Select function number: ");
700 int item
= atoi(cmd
);
710 terminate_calibration(1);
713 monitor_calibration_progress(0);
716 program_smart_eeprom();
722 if (tolower(*cmd
) == 'q')
725 pmsg("Illegal response. Please enter 1-6,Q\n");
730 pmsg("Illegal response. Please enter 1-6,Q\n");
734 pmsg("End apctest.\n");
736 pmsg("APC Smart Driver not configured.\n");
740 #ifdef HAVE_APCSMART_DRIVER
741 static void smart_ttymode(void)
744 // This is crap. Windows has no sane way (that I can find) to watch two
745 // fds for activity from a single thread without involving the overly
746 // complex "overlapped" io junk. So we will resort to polling.
748 // Save any existing timeouts on the UPS fd
749 HANDLE hnd
= (HANDLE
)_get_osfhandle(ups
->fd
);
750 COMMTIMEOUTS orig_ups_ct
;
751 GetCommTimeouts(hnd
, &orig_ups_ct
);
753 // Reset UPS fd timeout to 50 msec
755 ct
.ReadIntervalTimeout
= MAXDWORD
;
756 ct
.ReadTotalTimeoutMultiplier
= 0;
757 ct
.ReadTotalTimeoutConstant
= 50;
758 ct
.WriteTotalTimeoutMultiplier
= 0;
759 ct
.WriteTotalTimeoutConstant
= 0;
760 SetCommTimeouts(hnd
, &ct
);
762 pmsg("Enter an ESC character (or ctl-[) to exit.\n\n");
767 // Waits up to 50 msec for a char from the UPS
768 if (read(ups
->fd
, &ch
, 1) == 1)
771 // Check if keyboard key was hit and read it (only Windows would
772 // have a function dedicated to checking if a key has been pressed!)
779 write(ups
->fd
, &ch
, 1);
783 // Restore original timeouts on UPS fd
784 SetCommTimeouts(hnd
, &orig_ups_ct
);
787 struct termios t
, old_term_params
;
791 if (tcgetattr(0, &old_term_params
) != 0) {
792 pmsg("Cannot tcgetattr()\n");
797 t
.c_cc
[VMIN
] = 1; /* satisfy read after 1 char */
799 t
.c_iflag
&= ~(BRKINT
| IGNPAR
| PARMRK
| INPCK
|
800 ISTRIP
| ICRNL
| IXON
| IXOFF
| INLCR
| IGNCR
);
802 t
.c_lflag
&= ~(ICANON
| ISIG
| NOFLSH
| TOSTOP
);
803 tcflush(0, TCIFLUSH
);
805 if (tcsetattr(0, TCSANOW
, &t
) == -1) {
806 pmsg("Cannot tcsetattr()\n");
810 pmsg("Enter an ESC character (or ctl-[) to exit.\n\n");
812 tcflush(ups
->fd
, TCIOFLUSH
);
816 FD_SET(ups
->fd
, &rfds
);
817 stat
= select((ups
->fd
) + 1, &rfds
, NULL
, NULL
, NULL
);
819 pmsg("select() failed.\n");
822 if (FD_ISSET(0, &rfds
)) {
823 if (read(0, &ch
, 1) != 1)
829 write(ups
->fd
, &ch
, 1);
831 if (FD_ISSET(ups
->fd
, &rfds
)) {
832 if (read(ups
->fd
, &ch
, 1) != 1)
839 tcsetattr(0, TCSANOW
, &old_term_params
);
844 /* Do runtime battery calibration */
845 static void smart_calibration(void)
849 int stat
, monitor
, elapse
;
852 pmsg("First ensure that we have a good link and \n"
853 "that the UPS is functionning normally.\n");
854 pmsg("Simulating UPSlinkCheck ...\n");
856 tcflush(ups
->fd
, TCIOFLUSH
);
858 /* Start really simply */
860 stat
= write(ups
->fd
, &cmd
, 1);
862 pmsg("Bad status from write: %s\n", strerror(errno
));
864 stat
= getline(answer
, sizeof(answer
), ups
);
865 pmsg("Wrote: Y Got: %s\n", answer
);
866 if (stat
== FAILURE
) {
867 pmsg("getline failed. Apparently the link is not up.\n"
872 pmsg("Attempting to use smart_poll() ...\n");
873 ans
= smart_poll('Y', ups
);
874 pmsg("Sent: Y Got: %s ", ans
);
875 if (strcmp(ans
, "SM") == 0) {
876 pmsg("Good -- smart_poll() works!.\n\n");
878 pmsg("Not good.\nGiving up.\n");
882 pmsg("Checking estimated runtime ...\n");
883 ans
= smart_poll('j', ups
);
884 if (*ans
>= '0' && *ans
<= '9') {
887 pmsg("Current runtime is %d minutes\n", rt
);
889 pmsg("Unexpected response from UPS: %s\n", ans
);
893 pmsg("Checking for battery level ...\n");
894 ans
= smart_poll('f', ups
);
895 if (strncmp(ans
, "100.0", 5) == 0) {
896 pmsg("Battery level is 100.0 -- OK\n");
898 pmsg("Battery level %s insufficient to run test.\n", ans
);
902 pmsg("\nThe battery calibration should automatically end\n"
903 "when the battery level drops below about 25, depending\n"
905 "I can also optionally monitor the progress\n"
906 "and stop the calibration if it goes below 10. However,\n"
907 "in the case of a new battery this may prematurely end the\n"
908 "calibration loosing the effect.\n\n");
910 ans
= get_cmd("Do you want me to stop the calibration\n"
911 "if the battery level goes too low? (y/n): ");
913 if (*ans
== 'Y' || *ans
== 'y')
918 pmsg("\nSending Battery Calibration command. ...\n");
920 ans
= smart_poll('D', ups
);
921 if (*ans
== '!' || strcmp(ans
, "OK") == 0) {
922 pmsg("UPS has initiated battery calibration.\n");
924 pmsg("Unexpected response from UPS: %s\n", ans
);
928 start_time
= time(NULL
);
929 monitor_calibration_progress(monitor
);
930 elapse
= time(NULL
) - start_time
;
931 pmsg("On battery %d sec or %dm%ds.\n", elapse
, elapse
/ 60, elapse
% 60);
934 static void terminate_calibration(int ask
)
939 pmsg("\nCAUTION! Don't use this command unless the UPS\n"
940 "is already doing a calibration.\n");
941 cmd
= get_cmd("Are you sure? (yes/no): ");
942 if (strcmp(cmd
, "yes") != 0)
946 pmsg("\nAttempting to abort calibration ...\n");
947 ans
= smart_poll('D', ups
); /* abort calibration */
948 if (*ans
== '$' || strcmp(ans
, "NO") == 0) {
949 pmsg("Battery Runtime Calibration terminated.\n");
950 pmsg("Checking estimated runtime ...\n");
951 ans
= smart_poll('j', ups
);
952 if (*ans
>= '0' && *ans
<= '9') {
955 pmsg("Updated runtime is %d\n", rt
);
957 pmsg("Unexpected response from UPS: %s\n", ans
);
960 pmsg("Response to abort request: %s\n", ans
);
965 static void monitor_calibration_progress(int monitor
)
972 pmsg("Monitoring the calibration progress ...\n"
973 "To stop the calibration, enter a return.\n");
982 FD_SET(ups
->fd
, &rfds
);
983 FD_SET(STDIN_FILENO
, &rfds
);
988 retval
= select((ups
->fd
) + 1, &rfds
, NULL
, NULL
, &tv
);
992 if (++count
>= max_count
) {
993 ans
= smart_poll('f', ups
); /* Get battery charge */
994 percent
= (int)strtod(ans
, NULL
);
995 pmsg("\nBattery charge %d\n", percent
);
998 if (monitor
&& percent
<= 10) {
999 pmsg("Battery charge less than 10% terminating calibration ...\n");
1000 terminate_calibration(0);
1004 max_count
= 2; /* report faster */
1007 ans
= smart_poll('j', ups
); /* Get runtime */
1008 if (*ans
>= '0' && *ans
<= '9') {
1011 pmsg("Remaining runtime is %d minutes\n", rt
);
1012 if (monitor
&& rt
< 2) {
1013 pmsg("Runtime less than 2 minutes terminating calibration ...\n");
1014 terminate_calibration(0);
1020 write(STDOUT_FILENO
, &period
, 1);
1025 if (errno
== EINTR
|| errno
== EAGAIN
)
1028 pmsg("\nSelect error. ERR=%s\n", strerror(errno
));
1035 /* *ANY* user input aborts the calibration */
1036 if (FD_ISSET(STDIN_FILENO
, &rfds
)) {
1037 read(STDIN_FILENO
, &cmd
, 1);
1038 pmsg("\nUser input. Terminating calibration ...\n");
1039 terminate_calibration(0);
1043 if (FD_ISSET(ups
->fd
, &rfds
)) {
1044 read(ups
->fd
, &cmd
, 1);
1046 pmsg("\nBattery Runtime Calibration terminated by UPS.\n");
1047 pmsg("Checking estimated runtime ...\n");
1048 ans
= smart_poll('j', ups
);
1049 if (*ans
>= '0' && *ans
<= '9') {
1052 pmsg("Remaining runtime is %d minutes\n", rt
);
1054 pmsg("Unexpected response from UPS: %s\n", ans
);
1057 /* ignore normal characters */
1058 } else if (cmd
== '!' || cmd
== '+' || cmd
== ' ' ||
1059 cmd
== '\n' || cmd
== '\r') {
1062 pmsg("\nUPS sent: %c\n", cmd
);
1068 static void program_smart_eeprom(void)
1073 pmsg("This is the EEPROM programming section of apctest.\n"
1074 "Please select the function you want to perform.\n");
1078 " 1) Print EEPROM values\n"
1079 " 2) Change Battery date\n"
1080 " 3) Change UPS name\n"
1081 " 4) Change sensitivity\n"
1082 " 5) Change alarm delay\n"
1083 " 6) Change low battery warning delay\n"
1084 " 7) Change wakeup delay\n"
1085 " 8) Change shutdown delay\n"
1086 " 9) Change low transfer voltage\n"
1087 "10) Change high transfer voltage\n"
1088 "11) Change battery return threshold percent\n"
1089 "12) Change output voltage when on batteries\n"
1090 "13) Change the self test interval\n"
1091 "14) Set EEPROM with conf file values\n"
1094 cmd
= get_cmd("Select function number: ");
1096 int item
= atoi(cmd
);
1100 print_eeprom_values(ups
);
1104 cmd
= get_cmd("Enter new battery date -- DD/MM/YY: ");
1105 if (strlen(cmd
) != 8 || cmd
[2] != '/' || cmd
[5] != '/') {
1106 pmsg("Date must be exactly DD/MM/YY\n");
1109 apcsmart_ups_program_eeprom(ups
, CI_BATTDAT
, cmd
);
1113 cmd
= get_cmd("Enter new UPS name -- max 8 chars: ");
1114 if (strlen(cmd
) == 0 || strlen(cmd
) > 8) {
1115 pmsg("Name must be between 1 and 8 characters long.\n");
1118 apcsmart_ups_program_eeprom(ups
, CI_IDEN
, cmd
);
1122 cmd
= get_cmd("Enter new sensitivity: ");
1123 apcsmart_ups_program_eeprom(ups
, CI_SENS
, cmd
);
1127 cmd
= get_cmd("Enter new alarm delay: ");
1128 apcsmart_ups_program_eeprom(ups
, CI_DALARM
, cmd
);
1132 cmd
= get_cmd("Enter new low battery delay: ");
1133 apcsmart_ups_program_eeprom(ups
, CI_DLBATT
, cmd
);
1137 cmd
= get_cmd("Enter new wakeup delay: ");
1138 apcsmart_ups_program_eeprom(ups
, CI_DWAKE
, cmd
);
1142 cmd
= get_cmd("Enter new shutdown delay: ");
1143 apcsmart_ups_program_eeprom(ups
, CI_DSHUTD
, cmd
);
1147 cmd
= get_cmd("Enter new low transfer voltage: ");
1148 apcsmart_ups_program_eeprom(ups
, CI_LTRANS
, cmd
);
1152 cmd
= get_cmd("Enter new high transfer voltage: ");
1153 apcsmart_ups_program_eeprom(ups
, CI_HTRANS
, cmd
);
1157 cmd
= get_cmd("Enter new battery return level: ");
1158 apcsmart_ups_program_eeprom(ups
, CI_RETPCT
, cmd
);
1162 cmd
= get_cmd("Enter new output voltage on batteries: ");
1163 apcsmart_ups_program_eeprom(ups
, CI_NOMOUTV
, cmd
);
1167 cmd
= get_cmd("Enter new self test interval: ");
1168 apcsmart_ups_program_eeprom(ups
, CI_STESTI
, cmd
);
1172 pmsg("The EEPROM values to be changed will be taken from\n"
1173 "the configuration directives in your apcupsd.conf file.\n");
1174 cmd
= get_cmd("Do you want to continue? (Y/N): ");
1175 if (*cmd
!= 'y' && *cmd
!= 'Y') {
1176 pmsg("EEPROM changes NOT made.\n");
1179 apcsmart_ups_program_eeprom(ups
, -1, NULL
);
1183 if (tolower(*cmd
) == 'q')
1186 pmsg("Illegal response. Please enter 1-14,Q\n");
1190 pmsg("Illegal response. Please enter 1-14,Q\n");
1194 pmsg("End EEPROM programming.\n");
1197 static void smart_test1(void)
1199 char *ans
, *p
, *o
, cmd
;
1205 char locale
, locale1
, locale2
;
1208 pmsg("I am going to run through the series of queries of the UPS\n"
1209 "that are used in initializing apcupsd.\n\n");
1211 pmsg("Simulating UPSlinkCheck ...\n");
1212 tcflush(ups
->fd
, TCIOFLUSH
);
1214 /* Start really simply */
1216 stat
= write(ups
->fd
, &cmd
, 1);
1218 pmsg("Bad status from write: %s\n", strerror(errno
));
1220 stat
= getline(answer
, sizeof(answer
), ups
);
1221 pmsg("Wrote: Y Got: %s\n", answer
);
1222 if (stat
== FAILURE
) {
1223 pmsg("getline failed. Apparently the link is not up.\n"
1228 pmsg("Attempting to use smart_poll() ...\n");
1229 ans
= smart_poll('Y', ups
);
1230 pmsg("Sent: Y Got: %s ", ans
);
1231 if (strcmp(ans
, "SM") == 0) {
1232 pmsg("Good -- smart_poll() works!.\n\n");
1234 pmsg("Not good.\nGiving up.\n");
1238 pmsg("Going to ask for valid commands...\n");
1240 stat
= write(ups
->fd
, &cmd
, 1);
1242 pmsg("Bad response from write: %d %s\n", stat
, strerror(errno
));
1245 stat
= getline(answer
, sizeof(answer
), ups
);
1246 pmsg("Wrote: a Got: %s\n", answer
);
1247 if (stat
== FAILURE
) {
1248 pmsg("Cannot get the list of valid commands (a very old ups perhaps ?).\n");
1251 /* Get protocol version */
1252 for (p
= answer
, o
= parts
; *p
&& *p
!= '.'; p
++)
1256 pmsg("Protocol version is: %s\n", parts
);
1260 /* Get alert characters */
1261 for (o
= parts
; *p
&& *p
!= '.'; p
++) {
1264 *o
++ = *p
+ 'A' - 1;
1271 pmsg("Alert characters are: %s\n", parts
);
1275 /* Get command characters */
1276 for (o
= parts
; *p
; p
++) {
1279 *o
++ = *p
+ 'A' - 1;
1286 pmsg("Command characters are: %s\n", parts
);
1287 pmsg("\nNow running through apcupsd get_UPS capabilities().\n"
1288 "NA indicates that the feature is Not Available\n\n");
1290 pmsg("UPS Status: %s\n", smart_poll(ups
->UPS_Cmd
[CI_STATUS
], ups
));
1292 pmsg("Line quality: %s\n", smart_poll(ups
->UPS_Cmd
[CI_LQUAL
], ups
));
1294 pmsg("Reason for last transfer to batteries: %s\n",
1295 smart_poll(ups
->UPS_Cmd
[CI_WHY_BATT
], ups
));
1297 pmsg("Self-Test Status: %s\n", smart_poll(ups
->UPS_Cmd
[CI_ST_STAT
], ups
));
1299 pmsg("Line Voltage: %s\n", smart_poll(ups
->UPS_Cmd
[CI_VLINE
], ups
));
1301 pmsg("Line Voltage Max: %s\n", smart_poll(ups
->UPS_Cmd
[CI_VMAX
], ups
));
1303 pmsg("Line Voltage Min: %s\n", smart_poll(ups
->UPS_Cmd
[CI_VMIN
], ups
));
1305 pmsg("Output Voltage: %s\n", smart_poll(ups
->UPS_Cmd
[CI_VOUT
], ups
));
1307 pmsg("Batt level percent: %s\n", smart_poll(ups
->UPS_Cmd
[CI_BATTLEV
], ups
));
1309 pmsg("Batt voltage: %s\n", smart_poll(ups
->UPS_Cmd
[CI_VBATT
], ups
));
1311 pmsg("UPS Load: %s\n", smart_poll(ups
->UPS_Cmd
[CI_LOAD
], ups
));
1313 pmsg("Line freq: %s\n", smart_poll(ups
->UPS_Cmd
[CI_FREQ
], ups
));
1315 pmsg("Runtime left: %s\n", smart_poll(ups
->UPS_Cmd
[CI_RUNTIM
], ups
));
1317 pmsg("UPS Internal temp: %s\n", smart_poll(ups
->UPS_Cmd
[CI_ITEMP
], ups
));
1319 pmsg("Dip switch settings: %s\n", smart_poll(ups
->UPS_Cmd
[CI_DIPSW
], ups
));
1321 pmsg("Register 1: %s\n", smart_poll(ups
->UPS_Cmd
[CI_REG1
], ups
));
1323 pmsg("Register 2: %s\n", smart_poll(ups
->UPS_Cmd
[CI_REG2
], ups
));
1325 pmsg("Register 3: %s\n", smart_poll('8', ups
));
1327 pmsg("Sensitivity: %s\n", smart_poll(ups
->UPS_Cmd
[CI_SENS
], ups
));
1329 pmsg("Wakeup delay: %s\n", smart_poll(ups
->UPS_Cmd
[CI_DWAKE
], ups
));
1331 pmsg("Sleep delay: %s\n", smart_poll(ups
->UPS_Cmd
[CI_DSHUTD
], ups
));
1333 pmsg("Low transfer voltage: %s\n", smart_poll(ups
->UPS_Cmd
[CI_LTRANS
], ups
));
1335 pmsg("High transfer voltage: %s\n", smart_poll(ups
->UPS_Cmd
[CI_HTRANS
], ups
));
1337 pmsg("Batt charge for return: %s\n", smart_poll(ups
->UPS_Cmd
[CI_RETPCT
], ups
));
1339 pmsg("Alarm status: %s\n", smart_poll(ups
->UPS_Cmd
[CI_DALARM
], ups
));
1341 pmsg("Low battery shutdown level: %s\n", smart_poll(ups
->UPS_Cmd
[CI_DLBATT
],
1344 pmsg("UPS Name: %s\n", smart_poll(ups
->UPS_Cmd
[CI_IDEN
], ups
));
1346 pmsg("UPS Self test interval: %s\n", smart_poll(ups
->UPS_Cmd
[CI_STESTI
], ups
));
1348 pmsg("UPS manufacture date: %s\n", smart_poll(ups
->UPS_Cmd
[CI_MANDAT
], ups
));
1350 pmsg("UPS serial number: %s\n", smart_poll(ups
->UPS_Cmd
[CI_SERNO
], ups
));
1352 pmsg("Date battery replaced: %s\n", smart_poll(ups
->UPS_Cmd
[CI_BATTDAT
], ups
));
1354 pmsg("Output voltage when on batteries: %s\n",
1355 smart_poll(ups
->UPS_Cmd
[CI_NOMOUTV
], ups
));
1357 pmsg("Nominal battery voltage: %s\n", smart_poll(ups
->UPS_Cmd
[CI_NOMBATTV
], ups
));
1359 pmsg("Percent humidity: %s\n", smart_poll(ups
->UPS_Cmd
[CI_HUMID
], ups
));
1361 pmsg("Ambient temperature: %s\n", smart_poll(ups
->UPS_Cmd
[CI_ATEMP
], ups
));
1363 pmsg("Firmware revision: %s\n", smart_poll(ups
->UPS_Cmd
[CI_REVNO
], ups
));
1365 pmsg("Number of external batteries installed: %s\n",
1366 smart_poll(ups
->UPS_Cmd
[CI_EXTBATTS
], ups
));
1368 pmsg("Number of bad batteries installed: %s\n",
1369 smart_poll(ups
->UPS_Cmd
[CI_BADBATTS
], ups
));
1371 pmsg("UPS model as defined by UPS: %s\n", smart_poll(ups
->UPS_Cmd
[CI_UPSMODEL
],
1374 pmsg("UPS EPROM capabilities string: %s\n", (ans
=
1375 smart_poll(ups
->UPS_Cmd
[CI_EPROM
], ups
)));
1376 pmsg("The EPROM string is %d characters long!\n", strlen(ans
));
1378 pmsg("Hours since last self test: %s\n", smart_poll(ups
->UPS_Cmd
[CI_ST_TIME
],
1381 pmsg("\nThat is all for now.\n");
1386 static void do_usb_testing(void)
1388 #ifdef HAVE_USB_DRIVER
1392 pmsg("Hello, this is the apcupsd Cable Test program.\n"
1393 "This part of apctest is for testing USB UPSes.\n");
1395 pmsg("\nGetting UPS capabilities...");
1396 if (!usb_ups_get_capabilities(ups
))
1397 pmsg("FAILED\nSome or all tests may not work!\n");
1401 pmsg("\nPlease select the function you want to perform.\n");
1405 "1) Test kill UPS power\n"
1406 "2) Perform self-test\n"
1407 "3) Read last self-test result\n"
1408 "4) View/Change battery date\n"
1409 "5) View manufacturing date\n"
1410 "6) View/Change alarm behavior\n"
1411 "7) View/Change sensitivity\n"
1412 "8) View/Change low transfer voltage\n"
1413 "9) View/Change high transfer voltage\n"
1414 "10) Perform battery calibration\n"
1416 "12) View/Change self-test interval\n"
1419 cmd
= get_cmd("Select function number: ");
1421 int item
= atoi(cmd
);
1425 usb_kill_power_test();
1428 usb_run_self_test();
1431 usb_get_self_test_result();
1434 usb_set_battery_date();
1437 usb_get_manf_date();
1458 usb_set_self_test_interval();
1461 if (tolower(*cmd
) == 'q')
1464 pmsg("Illegal response. Please enter 1-12,Q\n");
1468 pmsg("Illegal response. Please enter 1-12,Q\n");
1472 pmsg("End apctest.\n");
1474 pmsg("USB Driver not configured.\n");
1478 #ifdef HAVE_USB_DRIVER
1480 static void usb_set_xferv(int lowhigh
)
1495 if (!usb_read_int_from_ups(ups
, ci
, &result
)) {
1496 pmsg("\nI don't know how to control the %s transfer voltage "
1497 " settings on your UPS.\n", text
);
1503 pmsg("Current %s transfer voltage setting: %d Volts\n", text
, result
);
1505 pmsg("Enter new %s transfer voltage (0 to cancel): ", text
);
1514 usb_write_int_to_ups(ups
, ci
, newval
, text
);
1516 // Give write a chance to work, then read new value
1519 usb_read_int_from_ups(ups
, ci
, &result
);
1521 if (result
!= newval
) {
1522 pmsg("FAILED to set new %s transfer voltage.\n\n"
1523 "This is probably because you entered a value that is out-of-range\n"
1524 "for your UPS. The acceptable range of values varies based on UPS\n"
1525 "model. The UPS has probably set the value as close as possible to\n"
1526 "what you requested.\n\n", text
);
1529 while (result
!= newval
);
1531 pmsg("New %s transfer voltage setting: %d Volts\n", text
, result
);
1534 static void usb_set_sens(void)
1539 if (!usb_read_int_from_ups(ups
, CI_SENS
, &result
)) {
1540 pmsg("\nI don't know how to control the alarm settings on your UPS.\n");
1544 pmsg("Current sensitivity setting: ");
1562 " L for Low sensitivity\n"
1563 " M for Medium sensitivity\n"
1564 " H for High sensitivity\n"
1565 " Q to Quit with no changes\n"
1567 cmd
= get_cmd("Select function: ");
1569 switch(tolower(*cmd
)) {
1571 usb_write_int_to_ups(ups
, CI_SENS
, 0, "CI_SENS");
1574 usb_write_int_to_ups(ups
, CI_SENS
, 1, "CI_SENS");
1577 usb_write_int_to_ups(ups
, CI_SENS
, 2, "CI_SENS");
1582 pmsg("Illegal response.\n");
1586 pmsg("Illegal response.\n");
1593 /* Delay needed for readback to work */
1596 usb_read_int_from_ups(ups
, CI_SENS
, &result
);
1597 pmsg("New sensitivity setting: ");
1614 static void usb_set_alarm(void)
1619 if (!usb_read_int_from_ups(ups
, CI_DALARM
, &result
)) {
1620 pmsg("\nI don't know how to control the alarm settings on your UPS.\n");
1624 pmsg("Current alarm setting: ");
1639 " E to Enable alarms\n"
1640 " D to Disable alarms\n"
1641 " Q to Quit with no changes\n"
1643 cmd
= get_cmd("Select function: ");
1645 switch(tolower(*cmd
)) {
1647 usb_write_int_to_ups(ups
, CI_DALARM
, 2, "CI_DALARM");
1650 usb_write_int_to_ups(ups
, CI_DALARM
, 1, "CI_DALARM");
1655 pmsg("Illegal response.\n");
1659 pmsg("Illegal response.\n");
1666 /* Delay needed for readback to work */
1669 usb_read_int_from_ups(ups
, CI_DALARM
, &result
);
1670 pmsg("New alarm setting: ");
1684 static void usb_kill_power_test(void)
1686 pmsg("\nThis test will attempt to power down the UPS.\n"
1687 "The USB cable should be plugged in to the UPS, but the\n"
1688 "AC power plug to the UPS should be DISCONNECTED.\n\n"
1689 "PLEASE DO NOT RUN THIS TEST WITH A COMPUTER CONNECTED TO YOUR UPS!!!\n\n"
1690 "Please enter any character when ready to continue: ");
1696 pmsg("calling kill_power function.\n");
1698 make_file(ups
, ups
->pwrfailpath
);
1699 initiate_hibernate(ups
);
1700 unlink(ups
->pwrfailpath
);
1703 pmsg("returned from kill_power function.\n");
1706 static void usb_get_self_test_result(void)
1710 if (!usb_read_int_from_ups(ups
, CI_ST_STAT
, &result
)) {
1711 pmsg("\nI don't know how to run a self test on your UPS\n"
1712 "or your UPS does not support self test.\n");
1716 pmsg("Result of last self test: ");
1731 pmsg("IN PROGRESS\n");
1734 pmsg("NO TEST PERFORMED\n");
1737 pmsg("UNKNOWN (%02x)\n", result
);
1742 static bool usb_clear_test_result()
1744 int timeout
, result
;
1746 pmsg("Clearing previous self test result...");
1748 // abort battery calibration in case it's in progress
1749 usb_write_int_to_ups(ups
, CI_ST_STAT
, 3, "SelftestStatus");
1751 if (!usb_write_int_to_ups(ups
, CI_ST_STAT
, 0, "SelftestStatus")) {
1756 for (timeout
= 0; timeout
< 10; timeout
++) {
1757 if (!usb_read_int_from_ups(ups
, CI_ST_STAT
, &result
)) {
1770 if (timeout
== 10) {
1778 static void usb_run_self_test(void)
1783 pmsg("\nThis test instructs the UPS to perform a self-test\n"
1784 "operation and reports the result when the test completes.\n\n");
1786 if (!usb_read_int_from_ups(ups
, CI_ST_STAT
, &result
)) {
1787 pmsg("I don't know how to run a self test on your UPS\n"
1788 "or your UPS does not support self test.\n");
1792 if (!usb_clear_test_result())
1795 pmsg("Initiating self test...");
1796 if (!usb_write_int_to_ups(ups
, CI_ST_STAT
, 1, "SelftestStatus")) {
1801 pmsg("INITIATED\n");
1803 pmsg("Waiting for test to complete...");
1805 for (timeout
= 0; timeout
< 40; timeout
++) {
1806 if (!usb_read_int_from_ups(ups
, CI_ST_STAT
, &result
)) {
1807 pmsg("ERROR READING STATUS\n");
1808 usb_write_int_to_ups(ups
, CI_ST_STAT
, 3, "SelftestStatus");
1813 pmsg("COMPLETED\n");
1820 if (timeout
== 40) {
1821 pmsg("TEST DID NOT COMPLETE\n");
1822 usb_write_int_to_ups(ups
, CI_ST_STAT
, 3, "SelftestStatus");
1826 usb_get_self_test_result();
1829 static int usb_get_battery_date(void)
1833 if (!usb_read_int_from_ups(ups
, CI_BATTDAT
, &result
)) {
1834 pmsg("\nI don't know how to access the battery date on your UPS\n"
1835 "or your UPS does not support the battery date feature.\n");
1841 * YYYY|YYYM|MMMD|DDDD
1846 pmsg("Current battery date: %02u/%02u/%04u\n",
1847 (result
& 0x1e0) >> 5, result
& 0x1f, 1980 + ((result
& 0xfe00) >> 9));
1852 static void usb_set_battery_date(void)
1855 int result
, day
, month
, year
, temp
, max
;
1857 if (!(result
= usb_get_battery_date()))
1860 cmd
= get_cmd("Enter new battery date (MM/DD/YYYY), blank to quit: ");
1861 if (!isdigit(cmd
[0]) || !isdigit(cmd
[1]) || cmd
[2] != '/' ||
1862 !isdigit(cmd
[3]) || !isdigit(cmd
[4]) || cmd
[5] != '/' ||
1863 !isdigit(cmd
[6]) || !isdigit(cmd
[7]) || !isdigit(cmd
[8]) ||
1864 !isdigit(cmd
[9]) || cmd
[10] != '\0' ||
1865 ((month
= strtoul(cmd
, NULL
, 10)) > 12) || (month
< 1) ||
1866 ((day
= strtoul(cmd
+ 3, NULL
, 10)) > 31) || (day
< 1) ||
1867 ((year
= strtoul(cmd
+ 6, NULL
, 10)) < 1980)) {
1868 pmsg("Invalid format.\n");
1872 result
= ((year
- 1980) << 9) | (month
<< 5) | day
;
1874 pmsg("Writing new date...");
1875 if (!usb_write_int_to_ups(ups
, CI_BATTDAT
, result
, "ManufactureDate")) {
1882 pmsg("Waiting for change to take effect...");
1883 for (max
= 0; max
< 10; max
++) {
1884 if (!usb_read_int_from_ups(ups
, CI_BATTDAT
, &temp
)) {
1900 usb_get_battery_date();
1903 static void usb_get_manf_date(void)
1907 if (!usb_read_int_from_ups(ups
, CI_MANDAT
, &result
)) {
1908 pmsg("\nI don't know how to access the manufacturing date on your UPS\n"
1909 "or your UPS does not support the manufacturing date feature.\n");
1915 * YYYY|YYYM|MMMD|DDDD
1920 pmsg("Manufacturing date: %02u/%02u/%04u\n",
1921 (result
& 0x1e0) >> 5, result
& 0x1f, 1980 + ((result
& 0xfe00) >> 9));
1924 static void usb_calibration()
1930 if (!ups
->UPS_Cap
[CI_ST_STAT
] ||
1931 !ups
->UPS_Cap
[CI_BATTLEV
] ||
1932 !ups
->UPS_Cap
[CI_LOAD
]) {
1933 pmsg("\nI don't know how to run a battery calibration on your UPS\n"
1934 "or your UPS does not support battery calibration\n");
1938 pmsg("This test instructs the UPS to perform a battery calibration\n"
1939 "operation and reports the result when the process completes.\n"
1940 "The battery level must be at 100%% and the load must be at least\n"
1941 "10%% to begin this test.\n\n");
1943 if (!usb_read_int_from_ups(ups
, CI_BATTLEV
, &result
)) {
1944 pmsg("Failed to read current battery level\n");
1948 if (result
== 100) {
1949 pmsg("Battery level is %d%% -- OK\n", result
);
1952 pmsg("Battery level %d%% is insufficient to run test.\n", result
);
1956 if (!usb_read_int_from_ups(ups
, CI_LOAD
, &result
)) {
1957 pmsg("Failed to read current load level\n");
1962 pmsg("Load level is %d%% -- OK\n", result
);
1965 pmsg("Load level %d%% is insufficient to run test.\n", result
);
1969 if (!usb_clear_test_result())
1972 pmsg("\nThe battery calibration should automatically end\n"
1973 "when the battery level drops below about 25%%.\n"
1974 "This process can take minutes or hours, depending on\n"
1975 "the size of your UPS and the load attached.\n\n");
1977 pmsg("Initiating battery calibration...");
1978 if (!usb_write_int_to_ups(ups
, CI_ST_STAT
, 2, "SelftestStatus")) {
1983 pmsg("INITIATED\n\n");
1985 pmsg("Waiting for calibration to complete...\n"
1986 "To abort the calibration, press ENTER.\n");
1994 FD_SET(STDIN_FILENO
, &rfds
);
1998 aborted
= select(STDIN_FILENO
+1, &rfds
, NULL
, NULL
, &tv
) == 1;
2000 while (fgetc(stdin
) != '\n')
2005 for (int i
= 0; i
< 100 && !aborted
; i
++) {
2006 while (kbhit() && !aborted
)
2007 aborted
= getch() == '\r';
2012 ts
.tv_nsec
= 100000000;
2013 nanosleep(&ts
, NULL
);
2019 pmsg("\n\nUser input detected; aborting calibration...");
2020 if (!usb_write_int_to_ups(ups
, CI_ST_STAT
, 3, "SelftestStatus")) {
2029 if (!usb_read_int_from_ups(ups
, CI_ST_STAT
, &result
)) {
2030 pmsg("\n\nError reading status; aborting calibration...");
2031 if (!usb_write_int_to_ups(ups
, CI_ST_STAT
, 3, "SelftestStatus")) {
2041 pmsg("\nCALIBRATION COMPLETED\n");
2045 // Output the battery level
2046 if (usb_read_int_from_ups(ups
, CI_BATTLEV
, &result
)) {
2047 if (ilastbl
== result
)
2050 pmsg("\nBattery level: %d%%", result
);
2057 usb_get_self_test_result();
2060 static void usb_test_alarm(void)
2064 if (!usb_read_int_from_ups(ups
, CI_TESTALARM
, &result
))
2066 pmsg("\nI don't know how to test the alarm on your UPS.\n");
2071 pmsg("Testing alarm...");
2072 usb_write_int_to_ups(ups
, CI_TESTALARM
, 1, "CI_TESTALARM");
2078 static int usb_get_self_test_interval(void)
2082 if (!usb_read_int_from_ups(ups
, CI_STESTI
, &result
))
2084 pmsg("\nI don't know how to access the self-test interval on your UPS\n"
2085 "or your UPS does not support the self-test interval feature.\n");
2089 pmsg("Current Self-test interval: ");
2105 pmsg("UNKNOWN (%02x)\n", result
);
2112 static void usb_set_self_test_interval(void)
2114 if (usb_get_self_test_interval() == -1)
2124 " Q to Quit with no changes\n"
2126 char *cmd
= get_cmd("Select function: ");
2129 if (*cmd
>= '0' && *cmd
<= '3')
2131 usb_write_int_to_ups(ups
, CI_STESTI
, *cmd
-'0', "CI_STESTI");
2134 else if (tolower(*cmd
) == 'q')
2137 pmsg("Illegal response.\n");
2141 pmsg("Illegal response.\n");
2145 /* Delay needed for readback to work */
2147 usb_get_self_test_interval();
2152 /* Get next input command from the terminal */
2153 static char *get_cmd(const char *prompt
)
2155 static char cmd
[1000];
2159 if (fgets(cmd
, sizeof(cmd
), stdin
) == NULL
)
2165 strip_trailing_junk(cmd
);
2170 /* Strip any trailing junk from the command */
2171 static void strip_trailing_junk(char *cmd
)
2175 p
= cmd
+ strlen(cmd
) - 1;
2177 /* strip trailing junk from command */
2178 while ((p
>= cmd
) && (*p
== '\n' || *p
== '\r' || *p
== ' '))
2182 #ifdef HAVE_APCSMART_DRIVER
2185 * EPROM commands and their values as parsed from the
2186 * ^Z eprom string returned by the UPS.
2195 /* Total number of EPROM commands */
2196 static int ncmd
= 0;
2198 static UPSINFO eeprom_ups
;
2201 * Table of the UPS command, the apcupsd configuration directive,
2202 * and an explanation of what the command sets in the EPROM.
2206 const char *config_directive
;
2207 const char *descript
;
2211 {'u', "HITRANSFER", "Upper transfer voltage", 'i', &eeprom_ups
.hitrans
},
2212 {'l', "LOTRANSFER", "Lower transfer voltage", 'i', &eeprom_ups
.lotrans
},
2213 {'e', "RETURNCHARGE", "Return threshold", 'i', &eeprom_ups
.rtnpct
},
2214 {'o', "OUTPUTVOLTS", "Output voltage on batts", 'i', &eeprom_ups
.NomOutputVoltage
},
2215 {'s', "SENSITIVITY", "Sensitivity", 'c', (int *)eeprom_ups
.sensitivity
},
2216 {'q', "LOWBATT", "Low battery warning", 'i', &eeprom_ups
.dlowbatt
},
2217 {'p', "SLEEP", "Shutdown grace delay", 'i', &eeprom_ups
.dshutd
},
2218 {'k', "BEEPSTATE", "Alarm delay", 'c', (int *)eeprom_ups
.beepstate
},
2219 {'r', "WAKEUP", "Wakeup delay", 'i', &eeprom_ups
.dwake
},
2220 {'E', "SELFTEST", "Self test interval", 'c', (int *)eeprom_ups
.selftest
},
2221 {0, NULL
, NULL
} /* Last entry */
2225 static void print_valid_eeprom_values(UPSINFO
*ups
)
2231 pmsg("\nValid EEPROM values for the %s\n\n", ups
->mode
.long_name
);
2233 memcpy(&eeprom_ups
, ups
, sizeof(UPSINFO
));
2235 pmsg("%-24s %-12s %-6s %s\n", " ", "Config", "Current", "Permitted");
2236 pmsg("%-24s %-12s %-6s %s\n", "Description", "Directive", "Value ", "Values");
2237 pmsg("===================================================================\n");
2239 for (i
= 0; i
< ncmd
; i
++) {
2240 for (j
= 0; cmd_table
[j
].cmd
; j
++) {
2241 if (cmd
[i
].cmd
== cmd_table
[j
].cmd
) {
2242 if (cmd_table
[j
].type
== 'c')
2243 asnprintf(val
, sizeof(val
), "%s", (char *)cmd_table
[j
].data
);
2245 asnprintf(val
, sizeof(val
), "%d", *cmd_table
[j
].data
);
2247 pmsg("%-24s %-12s %-6s ", cmd_table
[j
].descript
,
2248 cmd_table
[j
].config_directive
, val
);
2251 for (k
= cmd
[i
].num
; k
; k
--) {
2252 for (l
= cmd
[i
].size
; l
; l
--)
2264 pmsg("===================================================================\n");
2266 tcflush(ups
->fd
, TCIOFLUSH
);
2267 smart_poll('Y', ups
);
2268 smart_poll('Y', ups
);
2270 pmsg("Battery date: %s\n", smart_poll(ups
->UPS_Cmd
[CI_BATTDAT
], ups
));
2271 pmsg("UPS Name : %s\n", smart_poll(ups
->UPS_Cmd
[CI_IDEN
], ups
));
2276 * Parse EPROM command string returned by a ^Z command. We
2277 * pull out only entries that correspond to our UPS (locale).
2279 static void parse_eeprom_cmds(char *eprom
, char locale
)
2296 l
= *p
++; /* get locale */
2297 n
= *p
++ - '0'; /* get number of commands */
2298 s
= *p
++ - '0'; /* get character size */
2300 if (l
!= '4' && l
!= locale
) { /* skip this locale */
2305 cmd
[ncmd
].cmd
= c
; /* store command */
2306 cmd
[ncmd
].size
= s
; /* chare length of each value */
2307 cmd
[ncmd
].num
= n
; /* number of values */
2309 strncpy(cmd
[ncmd
].cmdvals
, p
, n
* s
); /* save values */
2315 for (i
= 0; i
< ncmd
; i
++) {
2316 printf("cmd=%c len=%d nvals=%d vals=%s\n", cmd
[i
].cmd
,
2317 cmd
[i
].size
, cmd
[i
].num
, cmd
[i
].cmdvals
);
2322 /*********************************************************************/
2323 static void print_eeprom_values(UPSINFO
*ups
)
2325 char locale
, locale1
, locale2
;
2327 pmsg("Doing prep_device() ...\n");
2329 if (!ups
->UPS_Cap
[CI_EPROM
])
2330 Error_abort0("Your model does not support EPROM programming.\n");
2332 if (ups
->UPS_Cap
[CI_REVNO
])
2333 locale1
= *(ups
->firmrev
+ strlen(ups
->firmrev
) - 1);
2337 if (ups
->UPS_Cap
[CI_UPSMODEL
])
2338 locale2
= *(ups
->upsmodel
+ strlen(ups
->upsmodel
) - 1);
2342 if (locale1
== locale2
&& locale1
== 0)
2343 Error_abort0("Your model does not support EPROM programming.\n");
2345 if (locale1
== locale2
)
2353 parse_eeprom_cmds(ups
->eprom
, locale
);
2354 print_valid_eeprom_values(ups
);