~ubuntu-branches/ubuntu/saucy/nut/saucy

« back to all changes in this revision

Viewing changes to drivers/belkin.c

  • Committer: Chuck Short
  • Date: 2013-05-13 12:57:25 UTC
  • Revision ID: zulcss@ubuntu.com-20130513125725-llq8wsohyhq9idsy
* Merge from Debian.  Remaining changes:
  - debian/control:
    + remove Build-Depends on libpowerman0-dev
    + remove nut-powerman-pdu
  - debian/nut-powerman-pdu.{install,manpages}: dropped for now
  - debian/{nut-cgi,nut-server}.postinst: add nut to the dialout and nut
    groups unconditonally to handle the upgrade from hardy release.
  - debian/source_nut.py, debian/{nut,nut-server,nut-client}.install,
    debian/rules: Install apport hooks for all top-level nut packages.
  - debian/rules: Use udev version for Ubuntu
  - debian/series, debian/patches/backport-fix-lp753661.patch: re-enabled
* Non-maintainer upload with fixes for wheezy.
* debian/nut-client.preinst: also revert /etc/nut/nut.conf mangling done
  by postinst during upgrade from lenny to squeeze (Really closes: #677054)
  Thanks to Andreas Beckmann for the review.
* Merge from Debian.  Remaining changes:
  - debian/control:
    + remove Build-Depends on libpowerman0-dev
    + remove nut-powerman-pdu
  - debian/nut-powerman-pdu.{install,manpages}: dropped for now
  - debian/{nut-cgi,nut-server}.postinst: add nut to the dialout and nut
    groups unconditonally to handle the upgrade from hardy release.
  - debian/source_nut.py, debian/{nut,nut-server,nut-client}.install,
    debian/rules: Install apport hooks for all top-level nut packages.
  - debian/rules: Use udev version for Ubuntu
  - debian/series, debian/patches/backport-fix-lp753661.patch: re-enabled
* Dropped the following patches, no longer required:
  - debian/patches/CVE-2012-2944.patch (included upstream)
* Non-maintainer upload with fixes for wheezy.
* Only remove /etc/init.d/nut from previous versions of nut in nut-server
  postinst if there are no local changes.
* Also remove /etc/init.d/nut in nut-client postinst. Thanks to 
  Laurent Bigonville for the hint.
* Only fix permissions of configfiles on first install.
* debian/control: Fix typo in package description. Thanks to Julien Cristau
  for spotting this.
* Non-maintainer upload.
* debian/nut-client.preinst: revert /etc/nut/nut.conf mangling done by older
  versions of the postinst (Closes: #677054)
* debian/rules: Stop the nut-client before nut-server on systems using
  static
  boot ordering (Closes: #679451)
* debian/nut-server.postinst: Remove /etc/init.d/nut on upgrade
  (Closes: #677822)
* Rename nut-server.lintian-overrides to nut-client.lintian-overrides and
  adjust overrides now that ups-monitor is shipped in nut-client package
  (Closes: #677947)
* Add debian/patches/0001-fix-upsmon-regression.patch: Fix upsmon/upssched
  regression (Taken from upstream) (Closes: #679513)
* Move nut metapackage to Section: metapackages
* Also create nut user when installing nut-client package and do not delete
  it on purge anymore (Closes: #682000)
* Drop /etc/default/nut → /etc/nut/nut.conf migration code, migration
  happends before squeeze release and this was against policy to have a
  maintainer script modifying a conffile in the first place (Closes: #684392)
* Add dependency against adduser and lsb-base on nut-client package
* Be sure that client is stopped before the server also when using
  dependencies based boot
* Fix package descriptions (Closes: #678068)
* Also install /bin/upssched-cmd in nut-client package as this script is
  referenced in default upssched.conf config file
* debian/watch: Update watch file
* Be sure that all maintainer scripts are returning 0 at their end
* New upstream release (Closes: #671444)
* acknowledges NMU (Closes: #613643)
* debian/nut-client.init: fix action "start" and use of log_*_*msg
  LSB log functions (Closes: #675619)
* debian/nut-server.preinst: remove obsolete file(s) left in
  /etc/udev/rules.d and related processing: udev files are now located
  in /lib/udev/rules, and there is no reason to modify the dedicated
  USB UPS rules (52-nut-usbups.rules) (Closes: #660072)
* debian/nut-server.init: rewrite to match upsd / drivers startup scope
* debian/nut-client.init: created to match upsmon startup scope
  (Closes: #634858)
* debian/nut.TODO.Debian, debian/Makefile.am: updated to reflect the above
* debian/rules: install nut-client.init, and update to reflect the above
* debian/control, debian/Makefile.am: updated to reflect the above
* debian/control:
  - add Breaks on nut-server (<< 2.6.3-1~)
  - bump Standards-Version to 3.9.3
* debian/nut-client.links: renamed from debian/nut-server.links, since
  ups-monitor is now provided by nut-client initscript
* debian/nut.README.Debian: renamed from nut-server.README.Debian,
  to provide it with both client and server packages
* debian/nut-server.install: add missing drivers (clone-outlet,
  liebert-esp2 and microdowell)
* debian/nut-server.manpages: add missing manual pages (apcsmart-old,
  ivtscd, liebert-esp2 and microdowell)
* SECURITY UPDATE: remote denial of service
 - debian/CVE-2012-2944.patch: limit the set of parsed characters to ' '
   through '~'
 - CVE-2012-2944
* Merge from Debian testing.  Remaining changes:
  - debian/control: Drop Build-Depends on libpowerman0-dev (currently in 
    universe)
  - debian/{nut-cgi,nut-server}.postinst: add nut to the dialout and nut 
    groups unconditonally to handle the upgrade from hardy release.
  - debian/nut-powerman-pdu.{install,manpages}: dropped for now.
  - debian/source_nut.py, debian/{nut,nut-server,nut-client}.install, 
    debian/rules: Install apport hooks for all top-level nut packages.
  - debian/rules: Use udev version for Ubuntu.
  - debian/series, debian/patches/backport-fix-lp753661.patch: re-enabled.
* New upstream release (Closes: #635186, #598741, #633756, #638221)
* debian/nut-server.{install,manpages}: add richcomm_usb
* debian/nut-server.install, debian/rules: install Avahi service file
* debian/rules, nut-client.install: install Augeas lenses
* debian/nut-server.README.Debian: clarify udev explanation (Closes: #529664)
* debian/patches/0001-fix_spelling_and_typo.patch,
  debian/patches/0003-libupsclient-version.patch: removed since these are now
  fixed upstream
* debian/patches/series: updated
* Merge from debian unstable.  Remaining changes:
  - debian/control: Drop Build-Depends on libpowerman0-dev (currently in 
    universe)
  - debian/{nut-cgi,nut-server}.postinst: add nut to the dialout and nut 
    groups unconditonally to handle the upgrade from hardy release.
  - debian/nut-powerman-pdu.{install,manpages}: dropped for now.
  - debian/source_nut.py, debian/{nut,nut-server,nut-client}.install, 
    debian/rules: Install apport hooks for all top-level nut packages.
  - debian/rules: Use udev version for Ubuntu.
  - debian/series, debian/patches/backport-fix-lp753661.patch: re-enabled.
* New upstream release (Closes: #594989)
* debian/control:
  - remove legacy Build-Depends for nut-hal-drivers on libdbus and libglib
  - Build-Depends-Indep on docbook-xsl for offline document
    generation (Closes: #635347)
* debian/nut-server.install: add apcsmart-old
* debian/nut-server.init:
  - add udev as Required-Start/Stop (Closes: #642412)
  - remove legacy support for /etc/default/nut (Closes: #638021)
* debian/patches/0003-libupsclient-version.patch: added to fix the missing
  libupsclient version info bump
* debian/libupsclient1-dev.links: update link name
* debian/libupsclient1.symbols: add with upscli_tryconnect
* debian/nut.TODO.Debian: update and complete the TODO list
* Fix FTBFS for Ubuntu (LP: #815760):
  - debian/control: Build-Depends-Indep on docbook-xsl for offline 
    document generation.
* Merge from Debian unstable (LP: #811976). Remaining changes:
  - debian/control: Drop Build-Depends on libpowerman0-dev (currently in 
    universe)
  - debian/{nut-cgi,nut-server}.postinst: add nut to the dialout and nut 
    groups unconditonally to handle the upgrade from hardy release.
  - debian/nut-powerman-pdu.{install,manpages}: dropped for now.
  - debian/source_nut.py, debian/{nut,nut-server,nut-client}.install, 
    debian/rules: Install apport hooks for all top-level nut packages.
  - debian/rules: Use udev version for Ubuntu.
  - debian/series, debian/patches/backport-fix-lp753661.patch: re-enabled.
* debian/nut.README.Debian: Adjust udev rules naming for permissions override
  (Closes: #529664)
* Re-add and refresh debian/patches/0001-fix_spelling_and_typo.patch:
  Some typos and spelling errors remain.
* Split nut package into nut-client and nut-server, keep nut package as
  metapackage
* Generate PDF and html doc and install it in nut-doc package
* debian/rules:
  - List non-installed files
  - Includes python-module.mk
  - Add flags to build documentation and install it
* debian/control:
  - Add python-nut package and add python build-dependency
  - Set nut-powerman-pdu priority to extras
  - Add nut-monitor package
  - Add nut-doc package and add required C/R/P
  - Add libups-nut-perl package
* debian/nut-server.prerm: Remove /var/run/nut during removal
* Merge from debian unstable.  Remaining changes:
  - debian/control:
    + Drop Build-Depends on libpowerman0-dev (currently in universe)
  - debian/{nut-cgi,nut}.postinst: add nut to the dialout and nut groups
    unconditonally to handle the upgrade from hardy release.
  - debian/nut-powerman-pdu.{install,manpages}: dropped for now.
  - debian/source_nut.py, debian/nut.install, debian/rules: Install apport hook.
  - debian/rules: Use udev version for Ubuntu.
* debian/patches/backport-fix-lp753661.patch: Refreshed.
* Drop changes due to .pc being not clean.
* New upstream release (Closes: #595953, #614842, #595773)
* debian/patches/*.patch: removed since these are now fixed upstream
* Drop HAL package and build-dependencies (Closes: #613197)
* debian/control:
  - Bump Standards-Version to 3.9.2 (no further changes)
  - Drop autotools build-dependencies (not needed anymore)
  - Drop non-existing build-dependencies
* debian/rules:
  - Correctly pass flags to configure
* Merge from debian unstable (LP: #789323).  Remaining changes:
  + debian/control:
    - Update maintainer as per spec.
    - Add Breaks on nut-hal-drivers to ensure we have correct udev version.
    - Drop libpowerman0-dev from the Build-Depends (currently in universe)
  + debian/{nut-cgi,nut}.postinst: add nut to the dialout and nut groups
    unconditonally to handle the upgrade from hardy release.
  + debian/nut-powerman-pdu.install, debian/nut-powerman-pdu.manpages: dropped for now.
  + debian/nul-hal-drivers.{docs,install,postinst,preinst}: Dropped since hal is in universe now
  + debian/nut.links: must create the init script link, used if the upse needs to be powered down
    (LP: #357583)
  + debian/source_nut.py, debian/nut.install, debian/rules: Install apport hook.
  + debian/patches/backport-fix-lp753661.patch
  + Dropped:
    - debian/patches/fix_pc_file.patch: replaced by debian's 0002-fix_libupsclient_pc.patch
* debian/patches/fix_pc_file.patch: add DEP3 patch header
* debian/patches/debian-changes-2.6.0-1: remove that accidental file
* debian/nut-snmp.docs: Distribute snmp.txt doc file (Closes: #548295)
* d/p/0001-fix_spelling_and_typo.patch: Update and refresh
* debian/nut.lintian-overrides: Fix typo
* debian/patch/0002-fix_libupsclient_pc.patch: Fix libupsclient.pc (Closes:
  #624255)
* debian/rules:
  - Switch to cdbs
  - Remove not existing configure options (Closes: #611813)
  - Drop Phony rules (Closes: #613699)
* debian/control:
  - Add cdbs build-dependency
* debian/patches/backport-fix-lp753661.patch: Backport fix 
  to trim extraneous end-of-line, in buggy HID string tables, 
  which results in upsc breaking the communication pipe.
  (LP: #753661)
* fix_pc_file.patch: fix .pc source files by using LIBSSL_LIBS instead of
  LIBSSL_LDFLAGS to avoid a FTBFS in packages that uses libupsclient.pc
  (LP: #743484)
* Merge from Debian unstable, remaining changes:
  + debian/control:
    - Update maintainer as per spec.
    - Add Breaks on nut-hal-drivers to ensure we have correct udev version.
    - Drop libpowerman0-dev from the Build-Depends (currently in universe)
  + debian/{nut-cgi,nut}.postinst: add nut to the dialout and nut groups
    unconditonally to hanle the upgrade from hardy release.
  + debian/nut-powerman-pdu.install, debian/nut-powerman-pdu.manpages: dropped for now.
  + debian/nul-hal-drivers.{docs,install,postinst,preinst}: Dropped since hal is in universe now
  + debian/nut.links: must create the init script link, used if the upse needs to be powered down
    (LP: #357583)
  + debian/source_nut.py, debian/nut.install, debian/rules: Install apport hook.
  + Dropped:
    - debian/patches/0002-fix_udev_action.patch: Accepted upstream.
    - debian/patches/0004-netvision-improvements-lp-600950: no longer needed.
    - debian/patches/0005-fix-nut-m4.patch: no longer needed.
    - debian/patches/9999-autoconf.patch: no longer needed.
* New upstream release (Closes: #575176, #588648, #609597, #687985)
* debian/patches/*.patch: removed since these are now fixed upstream
* debian/patches/0001-fix_spelling_and_typo.patch,
  debian/patches/series: reworked to match the new upstream release
* debian/nut.install, debian/nut.manpages: remove obsolete reference to
  megatec and megatec_usb, now respectively replaced by blazer_ser and
  blazer_usb
* debian/nut.docs: limit distributed documentation
* debian/control:
  - Wrap build-dependencies
  - Change nut-cgi Recommends to apache2 | httpd-cgi
* debian/nut.postinst: Only trigger USB subsystem, should Closes: #574769
* debian/patches/0002-fix_udev_action.patch: Use SUBSYSTEM instead of BUS
* debian/control, debian/rules, 
  debian/nut-hal-drivers.{docs,install,postinst,preinst}: Drop
  nut-hal-drivers since Nut doesnt go into universe.
* Split patches/debian-changes-2.4.3-2ubuntu1 into
  patches/0005-fix-nut-m4.patch and patches/9999-autoconf.patch
* Readd lost debian/patches0004-netvision-improvements-lp-600950.patch patch
  (LP: #707050)
* debian/patches/0002-fix_udev_action.patch:
  Change BUS to SUBSYSTEMS, since the former is deprecated. (LP: #692171)
* debian/nut.postinst: Uncomment missing call to adduser
* debian/control: Drop hal build dependency, we don't need the daemon to
  build the package. Add a hal dependency to nut-hal-drivers, which is the
  only thing that actually needs it.
* Merge from debian unstable.  Remaining changes:
  + debian/control:
    - Update maintainer as per spec.
    - Add Breaks on nut-hal-drivers to ensure we have correct udev version.
    - Drop libpowerman0-dev from the Build-Depends (currently in universe)
  + debian/{nut-cgi,nut}.postinst: add nut to the dialout and nut groups
    unconditonally to hanle the upgrade from hardy release.
  + debian/nut-powerman-pdu.install, debian/nut-powerman-pdu.manpages: dropped for now.
  + debian/nut.links: must create the init script link, used if the upse needs to be powered down
    (LP: #357583)
  + debian/nut.postinst: Update udevadm trigger.
    "libusb_get_report: error sending control message: 
     Operation not permitted" error on some UPS devices. (LP: #572262)
  + debian/source_nut.py, debian/nut.install, debian/rules: Install apport hook.
  + debian/patches/netvision-improvements-lp-600950.patch: Add improvements
    for netvision UPSes
  + Fix FTBFS with ld --as-needed.
  + Dropped:
    - debian/patches/03_udev_rules_change.dpatch: Use debian's instead.
    - debian/patches/04_nut_small-buffers.dpatch: Use debian's instead.
* debian/control:
  - Bump Standards-Version to 3.9.1
  - Update Vcs-* fields to new GIT repository
  - Add myself as Uploaders
* Switch to dpkg-source 3.0 (quilt) format (Closes: #573601)
* debian/patches/0001-low_speed_usb_ups.patch: Use patch system for changes
  that were applied directly in the source
* Add debian/gbp.conf file
* debian/watch: Bump version to 3
* Add debian/patches/0002-fix_udev_action.patch: Also set permission for
  "change" udev ACTION (Closes: #557178)
* debian/nut.postrm: Do not try to remove nut user is deluser is not
  installed anymore
* debian/nut.manpages: Install manpage nut.conf.5 (Closes: #528222)
* debian/copyright: Fix copyright-with-old-dh-make-debian-copyright
* Remove nut-snmp.lintian-overrides, not needed anymore
* debian/patches/0003-fix_spelling_and_typo.patch: Fix some spelling errors
* Add debian/libupsclient1.symbols file
* Add debian/nut.links: Re-add /etc/init.d/ups-monitor that was lost for
  some reasons (Closes: #592351)
* debian/nut.lintian-overrides: Add override for
  init.d-script-does-not-provide-itself /etc/init.d/ups-monitor
* Drop libupsclient1.post{inst,rm}: ldconfig call is added automatically by
  debhelper
* debian/libupsclient1-dev.install: Do not ship /lib/libupsclient.la anymore
* debian/rules: Remove dpatch logic as we are using package source version
  '3.0 (quilt)'
* debian/compat: Bump debhelper compatibility to 8
* Non-maintainer upload.
* drivers/libhid.c: Apply r2407 from upstream to fix bug with some
  low speed UPS devices. (Closes: #583371)
* Fix FTBFS with ld --as-needed.
* debian/patches/netvision-improvements-lp-600950.patch: Add improvements for netvision UPSes 
  (LP: #600950) 
* debian/source_nut.py, debian/nut.install, debian/rules: Install apport hook. 
* debian/patches/04_nut-small-buffers.dpatch: Fix "libusb_get_report: error sending control message: 
  Operation not permitted" error on some UPS devices. (LP: #572262)
* debian/nut.postinst: Revert dropping of --action=change. "add" events must
  not ever be triggered automatically.
* Add 03_udev_rules_change.dpatch: Run udev rules on change events, too.
* debian/control: grr...fix ftbfs. 
* Merge from debian testing.  Remaining changes (LP: #535152):
  + debian/control:
    - Update maintainer as per spec.
    - Add Breaks on nut-hal-drivers to ensure we have correct udev version.
    - Drop libpowerman0-dev from the Build-Depends (currently in universe)
  + debian/{nut-cgi,nut}.postinst: add nut to the dialout and nut groups
    unconditonally to hanle the upgrade from hardy release.
  + debian/nut-powerman-pdu.install, debian/nut-powerman-pdu.manpages: dropped for now.
  + debian/nut.links: must create the init script link, used if the upse needs to be powered down
    (LP: #357583)
  + debian/nut.postinst: Update udevadm trigger.
  + Dropped:
    - debian/patches/02-fix-trust-pw4130m.dpatch: No longer needed.
* New upstream release (Closes: #544390, #528222, #539747, #526811,
  #562064)
* debian/nut.install, debian/nut.manpages:
  - remove cyberpower driver and manpage
  - add bestfortress, clone and ivtscd drivers and manpages
* debian/rules:
  - change udev dir to /lib/udev (Closes: #522327)
  - replace deprecated calls to 'dh_clean -k' by dh_prep (Closes: #536599)
* debian/rules, debian/nut.install, debian/nut.install,
  debian/nut.README.Debian: install configuration files, without the
  sample suffix (Closes: #528641)
* debian/nut.links: restored (Closes: #522506)
* debian/nut.init:
  - source nut.conf instead of default/nut for POWEROFF_WAIT(Closes:
    #538173)
  - fix status checking (Closes: #538785)
  - improve detection of non configured system and beautify related
    output (Closes: #563112)
  - use 'invoke-rc.d' instead of calling the reboot script directly
  - add $remote_fs to Required-Start and Required-Stop
* debian/nut.postrm: remove udev files and simplify cleanup (Closes:
  #541629)
* debian/control:
  - remove Luca Filipozzi from the Uploaders list (Closes: #568987)
  - update Standards-Version to 3.8.4
  - remove the debconf dependency
  - bump debhelper version to (>= 7) in Build-Depends, for dh_prep
  - add Breaks on nut-hal-drivers to ensure we have correct udev version
* Remove debconf support since it was related to really old nut
  version (Closes: #518056):
  - remove nut-cgi.config, nut.config, nut-cgi.templates, nut.templates,
    and po/ directory
  - update nut-cgi.postinst
* debian/nut.dirs: remove /var/run/nut to conform to Debian Policy
* debian/nut.postint:
  - create /var/run/nut if needed
  - improve security checks
* debian/nut.README.Debian: add a security note for ups.conf
* debian/watch: URL update
* debian/patches/02-fix-trust-pw4130m.dpatch: Fix issues with Trust
  PW-4130M UPS. (LP: #447586) 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* belkin.c - model specific routines for Belkin Smart-UPS units.
2
2
 
3
 
   Copyright (C) 2000 Marcus M�ller <marcus@ebootis.de>
 
3
   Copyright (C) 2000 Marcus Müller <marcus@ebootis.de>
4
4
 
5
5
   based on:
6
6
 
28
28
#include "belkin.h"
29
29
 
30
30
#define DRIVER_NAME     "Belkin Smart protocol driver"
31
 
#define DRIVER_VERSION  "0.22"
 
31
#define DRIVER_VERSION  "0.24"
 
32
 
 
33
static int init_communication(void);
 
34
static int get_belkin_reply(char *buf);
32
35
 
33
36
/* driver description structure */
34
37
upsdrv_info_t upsdrv_info = {
35
38
        DRIVER_NAME,
36
39
        DRIVER_VERSION,
37
 
        "Marcus M�ller <marcus@ebootis.de>",
 
40
        "Marcus Müller <marcus@ebootis.de>",
38
41
        DRV_STABLE,
39
42
        { NULL }
40
43
};
41
44
 
42
45
static void send_belkin_command(char cmd, const char *subcmd, const char *data)
43
46
{
44
 
        ser_send(upsfd, "~00%c%03d%s%s", cmd, strlen(data) + 3, subcmd, data);
 
47
        ser_flush_io(upsfd);
 
48
 
 
49
        ser_send(upsfd, "~00%c%03d%s%s", cmd, (int)strlen(data) + 3, subcmd, data);
 
50
 
 
51
        upsdebugx(3, "Send Command: %s, %s", subcmd, data);
45
52
}
46
53
 
47
54
static int init_communication(void)
48
55
{
49
 
        int     i;
50
 
        int     res;
 
56
        int     i, res;
51
57
        char    temp[SMALLBUF];
52
58
 
53
 
        res = -1;
54
 
        for (i = 1; i <= 10 && res == -1; i++) {
55
 
                send_belkin_command(STATUS,MANUFACTURER,"");
 
59
        for (i = 0; i < 10; i++) {
 
60
                send_belkin_command(STATUS, MANUFACTURER, "");
56
61
                res = get_belkin_reply(temp);
 
62
 
 
63
                if (res > 0) {
 
64
                        /* return the number of retries needed before a valid reply is read (discard contents) */
 
65
                        return i;
 
66
                }
57
67
        }
58
68
 
59
 
        if (res == -1 || strcmp(temp,"BELKIN")) 
60
 
                return res;
61
 
 
62
 
        return 0;
 
69
        /* no valid reply read */
 
70
        return -1;
63
71
}
64
72
 
65
 
static char *get_belkin_field(const char *in, char *out, size_t outlen, 
66
 
        size_t num)
 
73
static char *get_belkin_field(const char *in, char *out, size_t outlen, size_t num)
67
74
{
68
75
        size_t  i, c = 1;
69
76
        char    *ptr;
73
80
                snprintf(out, outlen, "%s", in);
74
81
                ptr = strchr(out, ';');
75
82
 
76
 
                if (ptr)
 
83
                if (ptr) {
77
84
                        *ptr = '\0';
 
85
                }
78
86
 
79
87
                return out;
80
 
        }               
 
88
        }
81
89
 
82
90
        for (i = 0; i < strlen(in); i++) {
83
 
                if (in[i] == ';')
 
91
                if (in[i] == ';') {
84
92
                        c++;
 
93
                }
85
94
 
86
95
                if (c == num) {
87
96
                        snprintf(out, outlen, "%s", &in[i + 1]);
88
97
                        ptr = strchr(out, ';');
89
98
 
90
 
                        if (ptr)
 
99
                        if (ptr) {
91
100
                                *ptr = '\0';
 
101
                        }
 
102
 
92
103
                        return out;
93
104
                }
94
105
        }
96
107
        return NULL;
97
108
}
98
109
 
99
 
static int do_status(void)
 
110
static int get_belkin_reply(char *buf)
100
111
{
101
 
        char    temp[SMALLBUF], st[SMALLBUF];
102
 
        int     res;
103
 
 
104
 
        send_belkin_command(STATUS,STAT_STATUS,"");
105
 
        res = get_belkin_reply(temp);
106
 
        if (res == -1) {
107
 
                dstate_datastale();
 
112
        int     ret;
 
113
        long    cnt;
 
114
        char    tmp[8];
 
115
 
 
116
        usleep(25000);
 
117
 
 
118
        /* pull first 7 bytes to get data length - like ~00D004 */
 
119
        ret = ser_get_buf_len(upsfd, (unsigned char *)tmp, 7, 2, 0);
 
120
 
 
121
        if (ret != 7) {
 
122
                ser_comm_fail("Initial read returned %d bytes", ret);
 
123
                return -1;
 
124
        }
 
125
 
 
126
        tmp[7] = 0;
 
127
        cnt = strtol(tmp + 4, NULL, 10);
 
128
        upsdebugx(3, "Received: %s", tmp);
 
129
 
 
130
        if (cnt == 0) { /* possible to have ~00R000, return empty response */
 
131
                buf[0] = 0;
108
132
                return 0;
109
133
        }
110
134
 
111
 
        status_init();
112
 
 
113
 
        get_belkin_field(temp, st, sizeof(st), 6);
114
 
        if (*st == '1') {
115
 
                status_set("OFF");
116
 
 
117
 
        } else {        /* (OFF) and (OB | OL) are mutually exclusive */
118
 
 
119
 
                get_belkin_field(temp, st, sizeof(st), 2);
120
 
                if (*st == '1') {
121
 
                        status_set("OB");
122
 
 
123
 
                        send_belkin_command(STATUS,STAT_BATTERY,"");
124
 
                        res = get_belkin_reply(temp);
125
 
 
126
 
                        if (res == -1) {
127
 
                                dstate_datastale();
128
 
                                return 0;
129
 
                        }
130
 
 
131
 
                        get_belkin_field(temp, st, sizeof(st), 10);
132
 
                        res = atoi(st);
133
 
                        get_belkin_field(temp, st, sizeof(st), 2);
134
 
 
135
 
                        if (*st == '1' || res < LOW_BAT) 
136
 
                                status_set("LB");       /* low battery */
137
 
                }
138
 
                else
139
 
                        status_set("OL");       /* on line */
140
 
        }
141
 
 
142
 
        status_commit();
143
 
        dstate_dataok();
144
 
 
145
 
        return 1;
 
135
        if ((cnt < 0) || (cnt > 255)) {
 
136
                return -1;
 
137
        }
 
138
 
 
139
        /* give it time to respond to us */
 
140
        usleep(5000 * cnt);
 
141
 
 
142
        ret = ser_get_buf_len(upsfd, (unsigned char *)buf, cnt, 2, 0);
 
143
 
 
144
        buf[cnt] = 0;
 
145
        upsdebugx(3, "Received: %s", buf);
 
146
 
 
147
        if (ret != cnt) {
 
148
                ser_comm_fail("Second read returned %d bytes, expected %ld", ret, cnt);
 
149
                return -1;
 
150
        }
 
151
 
 
152
        ser_comm_good();
 
153
 
 
154
        return ret;
146
155
}
147
156
 
148
157
static int do_broken_rat(char *buf)
149
158
{
150
 
        int     ret, cnt;
 
159
        int     ret;
 
160
        long    cnt;
151
161
        char    tmp[8];
152
162
 
153
163
        usleep(25000);
154
164
 
155
 
        ret = ser_get_buf_len(upsfd, (unsigned char *)tmp, 7, 3, 0);
156
 
 
157
 
        if (ret != 7)
158
 
                return -1;
159
 
 
160
 
        tmp[7] = '\0';
161
 
        cnt = atoi(tmp + 4);
162
 
 
163
 
        if ((cnt < 1) || (cnt > 255))
164
 
                return -1;
165
 
 
 
165
        /* pull first 7 bytes to get data length - like ~00D004 */
 
166
        ret = ser_get_buf_len(upsfd, (unsigned char *)tmp, 7, 2, 0);
 
167
 
 
168
        if (ret != 7) {
 
169
                ser_comm_fail("Initial read returned %d bytes", ret);
 
170
                return -1;
 
171
        }
 
172
 
 
173
        tmp[7] = 0;
 
174
        cnt = strtol(tmp + 4, NULL, 10);
 
175
        upsdebugx(3, "Received: %s", tmp);
 
176
 
 
177
        if (cnt == 0) { /* possible to have ~00R000, return empty response */
 
178
                buf[0] = 0;
 
179
                return 0;
 
180
        }
 
181
 
 
182
        if ((cnt < 0) || (cnt > 255)) {
 
183
                return -1;
 
184
        }
 
185
 
 
186
        /* give it time to respond to us */
166
187
        usleep(5000 * cnt);
167
188
 
168
189
        /* firmware 001 only sends 50 bytes instead of the proper 53 */
169
 
        if (cnt == 53)
 
190
        if (cnt == 53) {
170
191
                cnt = 50;
171
 
 
172
 
        ret = ser_get_buf_len(upsfd, (unsigned char *)buf, 50, cnt, 0);
 
192
        }
 
193
 
 
194
        ret = ser_get_buf_len(upsfd, (unsigned char *)buf, cnt, 2, 0);
 
195
 
173
196
        buf[cnt] = 0;
 
197
        upsdebugx(3, "Received: %s", buf);
 
198
 
 
199
        if (ret != cnt) {
 
200
                ser_comm_fail("Second read returned %d bytes, expected %ld", ret, cnt);
 
201
                return -1;
 
202
        }
 
203
 
 
204
        ser_comm_good();
174
205
 
175
206
        return ret;
176
 
}       
177
 
 
178
 
static int init_ups_data(void)
179
 
{
180
 
        int     res;
181
 
        double  low, high;
182
 
        char    temp[SMALLBUF], st[SMALLBUF];
183
 
 
184
 
        send_belkin_command(STATUS, MODEL, "");
185
 
        res = get_belkin_reply(temp);
186
 
        if (res == -1)
187
 
                return res;
188
 
 
189
 
        dstate_setinfo("ups.model", "%s", temp);
190
 
 
191
 
        send_belkin_command(STATUS, VERSION_CMD, "");
192
 
        res = get_belkin_reply(temp);
193
 
        if (res == -1)
194
 
                return res;
195
 
 
196
 
        dstate_setinfo("ups.firmware", "%s", temp);
197
 
 
198
 
        /* deal with stupid firmware that breaks RAT */
199
 
 
200
 
        send_belkin_command(STATUS, RATING, "");
201
 
 
202
 
        if (!strcmp(temp, "001"))
203
 
                res = do_broken_rat(temp);
204
 
        else
205
 
                res = get_belkin_reply(temp);
206
 
 
207
 
        if (res > 0) {
208
 
                get_belkin_field(temp, st, sizeof(st), 8);
209
 
                low = atof(st) / 0.88;
210
 
 
211
 
                get_belkin_field(temp, st, sizeof(st), 9);
212
 
                high = atof(st) * 0.88;
213
 
 
214
 
                dstate_setinfo("input.transfer.low", "%03.1f", low);
215
 
                dstate_setinfo("input.transfer.high", "%03.1f", high);
216
 
        }
217
 
 
218
 
        ser_flush_io(upsfd);
219
 
 
220
 
        dstate_addcmd("load.off");
221
 
        dstate_addcmd("load.on");
222
 
        upsdrv_updateinfo();
223
 
        return 0;
224
207
}
225
208
 
226
209
/* normal idle loop - keep up with the current state of the UPS */
227
210
void upsdrv_updateinfo(void)
228
211
{
 
212
        static int retry = 0;
229
213
        int     res;
230
 
        double  val;
231
214
        char    temp[SMALLBUF], st[SMALLBUF];
232
215
 
233
 
        if (!do_status())
234
 
                return;
 
216
        send_belkin_command(STATUS, STAT_STATUS, "");
 
217
        res = get_belkin_reply(temp);
 
218
        if (res < 0) {
 
219
                if (retry < MAXTRIES) {
 
220
                        upsdebugx(1, "Communications with UPS lost: status read failed!");
 
221
                        retry++;
 
222
                } else {        /* too many retries */
 
223
                        upslogx(LOG_WARNING, "Communications with UPS lost: status read failed!");
 
224
                        dstate_datastale();
 
225
                }
 
226
                return;
 
227
        }
 
228
 
 
229
        if (retry) {    /* previous attempt had failed */
 
230
                upslogx(LOG_WARNING, "Communications with UPS re-established");
 
231
                retry = 0;
 
232
        }
 
233
 
 
234
        if (res == 0) {
 
235
                upsdebugx(1, "Ignoring empty return value after status query");
 
236
                return;
 
237
        }
 
238
 
 
239
        status_init();
 
240
 
 
241
        get_belkin_field(temp, st, sizeof(st), 6);
 
242
        if (*st == '1') {
 
243
                status_set("OFF");
 
244
        }
 
245
 
 
246
        get_belkin_field(temp, st, sizeof(st), 2);
 
247
        if (*st == '1') {
 
248
                status_set("OB");       /* on battery */
 
249
        } else {
 
250
                status_set("OL");       /* on line */
 
251
        }
 
252
 
 
253
        get_belkin_field(temp, st, sizeof(st), 16);
 
254
        dstate_setinfo("ups.beeper.status", "%s", (*st == '0' ? "disabled" : "enabled"));
 
255
 
 
256
        send_belkin_command(STATUS, STAT_BATTERY, "");
 
257
        res = get_belkin_reply(temp);
 
258
        if (res > 0) {
 
259
                /* report the compiled in battery charge where the driver assumes the battery is low */
 
260
                dstate_setinfo("battery.charge.low", "%d", LOW_BAT);
 
261
 
 
262
                get_belkin_field(temp, st, sizeof(st), 10);
 
263
                res = atoi(st);
 
264
                get_belkin_field(temp, st, sizeof(st), 2);
 
265
                
 
266
                if (*st == '1' || res < LOW_BAT) {
 
267
                        status_set("LB");       /* low battery */
 
268
                }
 
269
 
 
270
                get_belkin_field(temp, st, sizeof(st), 10);
 
271
                dstate_setinfo("battery.charge", "%.0f", strtod(st, NULL));
 
272
                
 
273
                get_belkin_field(temp, st, sizeof(st), 9);
 
274
                dstate_setinfo("battery.temperature", "%.0f", strtod(st, NULL));
 
275
 
 
276
                get_belkin_field(temp, st, sizeof(st), 7);
 
277
                dstate_setinfo("battery.voltage", "%.1f", strtod(st, NULL) / 10);
 
278
 
 
279
                get_belkin_field(temp, st, sizeof(st), 9);
 
280
                dstate_setinfo("ups.temperature", "%.0f", strtod(st, NULL));
 
281
        }
235
282
 
236
283
        send_belkin_command(STATUS, STAT_INPUT, "");
237
284
        res = get_belkin_reply(temp);
238
 
        if (res == -1)
239
 
                return;
240
 
 
241
 
        get_belkin_field(temp, st, sizeof(st), 3);
242
 
        val = atof(st) / 10;
243
 
        dstate_setinfo("input.voltage", "%05.1f", val);
244
 
 
245
 
        get_belkin_field(temp, st, sizeof(st), 2);
246
 
        val = atof(st) / 10;
247
 
        dstate_setinfo("input.frequency", "%.1f", val);
248
 
 
249
 
        send_belkin_command(STATUS,STAT_BATTERY, "");
250
 
        res = get_belkin_reply(temp);
251
 
        if (res == -1)
252
 
                return;
253
 
 
254
 
        get_belkin_field(temp, st, sizeof(st), 10);
255
 
        val = atof(st);
256
 
        dstate_setinfo("battery.charge", "%03.0f", val);
257
 
 
258
 
        get_belkin_field(temp, st, sizeof(st), 9);
259
 
        val = atof(st);
260
 
        dstate_setinfo("battery.temperature", "%03.0f", val);
261
 
 
262
 
        get_belkin_field(temp, st, sizeof(st), 7);
263
 
        val = atof(st) / 10;
264
 
        dstate_setinfo("battery.voltage", "%4.1f", val);
265
 
 
266
 
        get_belkin_field(temp, st, sizeof(st), 9);
267
 
        val = atof(st);
268
 
        dstate_setinfo("ups.temperature", "%03.0f", val);
 
285
        if (res > 0) {
 
286
                get_belkin_field(temp, st, sizeof(st), 3);
 
287
                dstate_setinfo("input.voltage", "%.1f", strtod(st, NULL) / 10);
 
288
 
 
289
                get_belkin_field(temp, st, sizeof(st), 2);
 
290
                dstate_setinfo("input.frequency", "%.1f", strtod(st, NULL) / 10);
 
291
        }
269
292
 
270
293
        send_belkin_command(STATUS, STAT_OUTPUT, "");
271
294
        res = get_belkin_reply(temp);
272
 
        if (res == -1)
273
 
                return;
274
 
 
275
 
        get_belkin_field(temp, st, sizeof(st), 2);
276
 
        val = atof(st) / 10;
277
 
        dstate_setinfo("output.frequency", "%.1f", val);
278
 
 
279
 
        get_belkin_field(temp, st, sizeof(st), 4);
280
 
        val = atof(st) / 10;
281
 
        dstate_setinfo("output.voltage", "%05.1f", val);
282
 
 
283
 
        get_belkin_field(temp, st, sizeof(st), 7);
284
 
        val = atof(st);
285
 
        dstate_setinfo("ups.load", "%03.0f", val);
286
 
}
287
 
 
288
 
static int get_belkin_reply(char *buf)
289
 
{
290
 
        int     ret, cnt;
291
 
        char    tmp[8];
292
 
 
293
 
        usleep(25000);
294
 
 
295
 
        /* pull first 7 bytes to get data length - like ~00S004 */
296
 
        ret = ser_get_buf_len(upsfd, (unsigned char *)tmp, 7, 3, 0);
297
 
 
298
 
        if (ret != 7) {
299
 
                ser_comm_fail("Initial read returned %d bytes", ret);
300
 
                return -1;
301
 
        }
302
 
 
303
 
        tmp[7] = 0;
304
 
        cnt = atoi(tmp + 4);
305
 
 
306
 
        if ((cnt < 1) || (cnt > 255))
307
 
                return -1;
308
 
 
309
 
        /* give it time to respond to us */
310
 
        usleep(5000 * cnt);
311
 
 
312
 
        ret = ser_get_buf_len(upsfd, (unsigned char *)buf, cnt, 3, 0);
313
 
 
314
 
        buf[cnt] = 0;
315
 
 
316
 
        if (ret != cnt) {
317
 
                ser_comm_fail("Second read returned %d bytes, expected %d",
318
 
                        ret, cnt);
319
 
                return -1;
320
 
        }
321
 
 
322
 
        ser_comm_good();
323
 
 
324
 
        return ret;
 
295
        if (res > 0) {
 
296
                get_belkin_field(temp, st, sizeof(st), 2);
 
297
                dstate_setinfo("output.frequency", "%.1f", strtod(st, NULL) / 10);
 
298
 
 
299
                get_belkin_field(temp, st, sizeof(st), 4);
 
300
                dstate_setinfo("output.voltage", "%.1f", strtod(st, NULL) / 10);
 
301
 
 
302
                get_belkin_field(temp, st, sizeof(st), 7);
 
303
                dstate_setinfo("ups.load", "%.0f", strtod(st, NULL));
 
304
        }
 
305
        
 
306
        send_belkin_command(STATUS, TEST_RESULT, "");
 
307
        res = get_belkin_reply(temp);
 
308
        if (res > 0) {
 
309
                get_belkin_field(temp, st, sizeof(st), 1);
 
310
                switch (*st)
 
311
                {
 
312
                case '0':
 
313
                        dstate_setinfo("ups.test.result", "%s", "No test performed");
 
314
                        break;
 
315
 
 
316
                case '1':
 
317
                        dstate_setinfo("ups.test.result", "%s", "Passed");
 
318
                        break;
 
319
 
 
320
                case '2':
 
321
                        dstate_setinfo("ups.test.result", "%s", "In progress");
 
322
                        break;
 
323
 
 
324
                case '3':
 
325
                case '4':
 
326
                        dstate_setinfo("ups.test.result", "%s", "10s test failed");
 
327
                        break;
 
328
 
 
329
                case '5':
 
330
                        dstate_setinfo("ups.test.result", "%s", "deep test failed");
 
331
                        break;
 
332
 
 
333
                case '6':
 
334
                        dstate_setinfo("ups.test.result", "%s", "Aborted");
 
335
                        break;
 
336
 
 
337
                default:
 
338
                        upsdebugx(3, "Unhandled test status '%c'", *st);
 
339
                        break;
 
340
                }
 
341
        }
 
342
 
 
343
        status_commit();
 
344
 
 
345
        dstate_dataok();
325
346
}
326
347
 
327
348
/* power down the attached load immediately */
330
351
        int     res;
331
352
 
332
353
        res = init_communication();
333
 
        if (res == -1)
 
354
        if (res < 0) {
334
355
                printf("Detection failed.  Trying a shutdown command anyway.\n");
 
356
        }
335
357
 
336
358
        /* tested on a F6C525-SER: this works when OL and OB */
337
359
 
347
369
        send_belkin_command(CONTROL, "SDA", "5");
348
370
}
349
371
 
 
372
/* handle "beeper.disable" */
 
373
static void do_beeper_off(void) {
 
374
        int     res;
 
375
        char    temp[SMALLBUF];
 
376
        const char      *arg;
 
377
 
 
378
        /* Compare the model name, as the BUZZER_OFF argument depends on it */
 
379
        send_belkin_command(STATUS, MODEL, "");
 
380
        res = get_belkin_reply(temp);
 
381
        if (res == -1)
 
382
                return;
 
383
 
 
384
        if (!strcmp(temp, "F6C1400-EUR")) {
 
385
                arg = BUZZER_OFF2;
 
386
        } else {
 
387
                arg = BUZZER_OFF0;
 
388
        }
 
389
 
 
390
        send_belkin_command(CONTROL,BUZZER,arg);
 
391
}
 
392
 
350
393
/* handle the "load.off" with some paranoia */
351
394
static void do_off(void)
352
395
{
375
418
 
376
419
static int instcmd(const char *cmdname, const char *extra)
377
420
{
 
421
        if (!strcasecmp(cmdname, "beeper.disable")) {
 
422
                do_beeper_off();
 
423
                return STAT_INSTCMD_HANDLED;
 
424
        }
 
425
 
 
426
        if (!strcasecmp(cmdname, "beeper.enable")) {
 
427
                send_belkin_command(CONTROL,BUZZER,BUZZER_ON);
 
428
                return STAT_INSTCMD_HANDLED;
 
429
        }
 
430
 
378
431
        if (!strcasecmp(cmdname, "load.off")) {
379
432
                do_off();
380
433
                return STAT_INSTCMD_HANDLED;
385
438
                return STAT_INSTCMD_HANDLED;
386
439
        }
387
440
 
 
441
        if (!strcasecmp(cmdname, "test.battery.start.quick")) {
 
442
                send_belkin_command(CONTROL,TEST,TEST_10SEC);
 
443
                return STAT_INSTCMD_HANDLED;
 
444
        }
 
445
 
 
446
        if (!strcasecmp(cmdname, "test.battery.start.deep")) {
 
447
                send_belkin_command(CONTROL,TEST,TEST_DEEP);
 
448
                return STAT_INSTCMD_HANDLED;
 
449
        }
 
450
 
 
451
        if (!strcasecmp(cmdname, "test.battery.stop")) {
 
452
                send_belkin_command(CONTROL,TEST,TEST_CANCEL);
 
453
                return STAT_INSTCMD_HANDLED;
 
454
        }
 
455
 
388
456
        upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
389
457
        return STAT_INSTCMD_UNKNOWN;
390
458
}
391
459
 
392
 
static void set_serialDTR0RTS1(void)
393
 
{
394
 
        /* set DTR to low and RTS to high */
395
 
        ser_set_dtr(upsfd, 0);
396
 
        ser_set_rts(upsfd, 1);
397
 
}
398
 
 
399
460
void upsdrv_help(void)
400
461
{
401
462
}
409
470
{
410
471
        upsfd = ser_open(device_path);
411
472
        ser_set_speed(upsfd, device_path, B2400);
412
 
        
413
 
        set_serialDTR0RTS1();
 
473
 
 
474
        /* set DTR to low and RTS to high */
 
475
        ser_set_dtr(upsfd, 0);
 
476
        ser_set_rts(upsfd, 1);
414
477
 
415
478
        sleep(1);
416
479
 
420
483
void upsdrv_initinfo(void)
421
484
{
422
485
        int     res;
 
486
        char    temp[SMALLBUF], st[SMALLBUF];
423
487
 
424
488
        res = init_communication();
425
 
        if (res == -1) {
 
489
        if (res < 0) {
426
490
                fatalx(EXIT_FAILURE, 
427
491
                        "Unable to detect an Belkin Smart protocol UPS on port %s\n"
428
492
                        "Check the cabling, port name or model name and try again", device_path
431
495
 
432
496
        dstate_setinfo("ups.mfr", "BELKIN");
433
497
 
434
 
        /* see what's out there */
435
 
        init_ups_data();
436
 
 
437
 
        printf("Detected %s on %s\n", dstate_getinfo("ups.model"),
438
 
                device_path);
 
498
        send_belkin_command(STATUS, MODEL, "");
 
499
        res = get_belkin_reply(temp);
 
500
        if (res > 0) {
 
501
                dstate_setinfo("ups.model", "%s", temp);
 
502
        }
 
503
 
 
504
        send_belkin_command(STATUS, VERSION_CMD, "");
 
505
        res = get_belkin_reply(temp);
 
506
        if (res > 0) {
 
507
                dstate_setinfo("ups.firmware", "%s", temp);
 
508
        }
 
509
 
 
510
        /* deal with stupid firmware that breaks RAT */
 
511
        send_belkin_command(STATUS, RATING, "");
 
512
 
 
513
        if (!strcmp(temp, "001")) {
 
514
                res = do_broken_rat(temp);
 
515
        } else {
 
516
                res = get_belkin_reply(temp);
 
517
        }
 
518
 
 
519
        if (res > 0) {
 
520
                get_belkin_field(temp, st, sizeof(st), 8);
 
521
                dstate_setinfo("input.transfer.low", "%.0f", strtod(st, NULL) / 0.88);
 
522
 
 
523
                get_belkin_field(temp, st, sizeof(st), 9);
 
524
                dstate_setinfo("input.transfer.high", "%.0f", strtod(st, NULL) * 0.88);
 
525
        }
 
526
 
 
527
        dstate_addcmd("beeper.disable");
 
528
        dstate_addcmd("beeper.enable");
 
529
        dstate_addcmd("load.off");
 
530
        dstate_addcmd("load.on");
 
531
        dstate_addcmd("test.battery.start.quick");
 
532
        dstate_addcmd("test.battery.start.deep");
 
533
        dstate_addcmd("test.battery.stop");
439
534
 
440
535
        upsh.instcmd = instcmd;
441
536
}