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

« back to all changes in this revision

Viewing changes to drivers/blazer_usb.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:
4
4
 * A document describing the protocol implemented by this driver can be
5
5
 * found online at "http://www.networkupstools.org/protocols/megatec.html".
6
6
 *
7
 
 * Copyright (C) 2008 - Arjen de Korte <adkorte-guest@alioth.debian.org>
 
7
 * Copyright (C) 2003-2009  Arjen de Korte <adkorte-guest@alioth.debian.org>
 
8
 * Copyright (C) 2011-2012  Arnaud Quette <arnaud.quette@free.fr>
8
9
 *
9
10
 * This program is free software; you can redistribute it and/or modify
10
11
 * it under the terms of the GNU General Public License as published by
27
28
#include "blazer.h"
28
29
 
29
30
#define DRIVER_NAME     "Megatec/Q1 protocol USB driver"
30
 
#define DRIVER_VERSION  "0.03"
 
31
#define DRIVER_VERSION  "0.08"
31
32
 
32
33
/* driver description structure */
33
34
upsdrv_info_t upsdrv_info = {
34
35
        DRIVER_NAME,
35
36
        DRIVER_VERSION,
36
 
        "Arjen de Korte <adkorte-guest@alioth.debian.org>",
 
37
        "Arjen de Korte <adkorte-guest@alioth.debian.org>\n" \
 
38
        "Arnaud Quette <arnaud.quette@free.fr>",
37
39
        DRV_BETA,
38
40
        { NULL }
39
41
};
43
45
static USBDevice_t              usbdevice;
44
46
static USBDeviceMatcher_t       *reopen_matcher = NULL;
45
47
static USBDeviceMatcher_t       *regex_matcher = NULL;
 
48
static int                                      langid_fix = -1;
46
49
 
47
50
static int (*subdriver_command)(const char *cmd, char *buf, size_t buflen) = NULL;
48
51
 
49
52
 
 
53
static int cypress_command(const char *cmd, char *buf, size_t buflen)
 
54
{
 
55
        char    tmp[SMALLBUF];
 
56
        int     ret;
 
57
        size_t  i;
 
58
 
 
59
        memset(tmp, 0, sizeof(tmp));
 
60
        snprintf(tmp, sizeof(tmp), "%s", cmd);
 
61
 
 
62
        for (i = 0; i < strlen(tmp); i += ret) {
 
63
 
 
64
                /* Write data in 8-byte chunks */
 
65
                /* ret = usb->set_report(udev, 0, (unsigned char *)&tmp[i], 8); */
 
66
                ret = usb_control_msg(udev, USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
 
67
                        0x09, 0x200, 0, &tmp[i], 8, 5000);
 
68
 
 
69
                if (ret <= 0) {
 
70
                        upsdebugx(3, "send: %s", ret ? usb_strerror() : "timeout");
 
71
                        return ret;
 
72
                }
 
73
        }
 
74
 
 
75
        upsdebugx(3, "send: %.*s", (int)strcspn(tmp, "\r"), tmp);
 
76
 
 
77
        memset(buf, 0, buflen);
 
78
 
 
79
        for (i = 0; (i <= buflen-8) && (strchr(buf, '\r') == NULL); i += ret) {
 
80
 
 
81
                /* Read data in 8-byte chunks */
 
82
                /* ret = usb->get_interrupt(udev, (unsigned char *)&buf[i], 8, 1000); */
 
83
                ret = usb_interrupt_read(udev, 0x81, &buf[i], 8, 1000);
 
84
 
 
85
                /*
 
86
                 * Any errors here mean that we are unable to read a reply (which
 
87
                 * will happen after successfully writing a command to the UPS)
 
88
                 */
 
89
                if (ret <= 0) {
 
90
                        upsdebugx(3, "read: %s", ret ? usb_strerror() : "timeout");
 
91
                        return ret;
 
92
                }
 
93
        }
 
94
 
 
95
        upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
 
96
        return i;
 
97
}
 
98
 
 
99
 
50
100
static int phoenix_command(const char *cmd, char *buf, size_t buflen)
51
101
{
52
102
        char    tmp[SMALLBUF];
53
103
        int     ret;
54
104
        size_t  i;
55
105
 
 
106
        for (i = 0; i < 8; i++) {
 
107
 
 
108
                /* Read data in 8-byte chunks */
 
109
                /* ret = usb->get_interrupt(udev, (unsigned char *)tmp, 8, 1000); */
 
110
                ret = usb_interrupt_read(udev, 0x81, tmp, 8, 1000);
 
111
 
 
112
                /*
 
113
                 * This USB to serial implementation is crappy. In order to read correct
 
114
                 * replies we need to flush the output buffers of the converter until we
 
115
                 * get no more data (ie, it times out).
 
116
                 */
 
117
                switch (ret)
 
118
                {
 
119
                case -EPIPE:            /* Broken pipe */
 
120
                        usb_clear_halt(udev, 0x81);
 
121
                case -ETIMEDOUT:        /* Connection timed out */
 
122
                        break;
 
123
                }
 
124
 
 
125
                if (ret < 0) {
 
126
                        upsdebugx(3, "flush: %s", usb_strerror());
 
127
                        break;
 
128
                }
 
129
 
 
130
                upsdebug_hex(4, "dump", tmp, ret);
 
131
        }
 
132
 
56
133
        memset(tmp, 0, sizeof(tmp));
57
134
        snprintf(tmp, sizeof(tmp), "%s", cmd);
58
135
 
69
146
                }
70
147
        }
71
148
 
72
 
        upsdebugx(3, "send: %.*s", strcspn(tmp, "\r"), tmp);
 
149
        upsdebugx(3, "send: %.*s", (int)strcspn(tmp, "\r"), tmp);
73
150
 
74
151
        memset(buf, 0, buflen);
75
152
 
84
161
                 * will happen after successfully writing a command to the UPS)
85
162
                 */
86
163
                if (ret <= 0) {
87
 
                        upsdebugx(3, "read: timeout");
88
 
                        return 0;
 
164
                        upsdebugx(3, "read: %s", ret ? usb_strerror() : "timeout");
 
165
                        return ret;
89
166
                }
90
167
        }
91
168
 
92
 
        upsdebugx(3, "read: %.*s", strcspn(buf, "\r"), buf);
 
169
        upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
93
170
        return i;
94
171
}
95
172
 
96
173
 
 
174
static int ippon_command(const char *cmd, char *buf, size_t buflen)
 
175
{
 
176
        char    tmp[64];
 
177
        int     ret;
 
178
        size_t  i;
 
179
 
 
180
        snprintf(tmp, sizeof(tmp), "%s", cmd);
 
181
 
 
182
        for (i = 0; i < strlen(tmp); i += ret) {
 
183
 
 
184
                /* Write data in 8-byte chunks */
 
185
                ret = usb_control_msg(udev, USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
 
186
                        0x09, 0x2, 0, &tmp[i], 8, 1000);
 
187
 
 
188
                if (ret <= 0) {
 
189
                        upsdebugx(3, "send: %s", (ret != -ETIMEDOUT) ? usb_strerror() : "Connection timed out");
 
190
                        return ret;
 
191
                }
 
192
        }
 
193
 
 
194
        upsdebugx(3, "send: %.*s", (int)strcspn(tmp, "\r"), tmp);
 
195
 
 
196
        /* Read all 64 bytes of the reply in one large chunk */
 
197
        ret = usb_interrupt_read(udev, 0x81, tmp, sizeof(tmp), 1000);
 
198
 
 
199
        /*
 
200
         * Any errors here mean that we are unable to read a reply (which
 
201
         * will happen after successfully writing a command to the UPS)
 
202
         */
 
203
        if (ret <= 0) {
 
204
                upsdebugx(3, "read: %s", (ret != -ETIMEDOUT) ? usb_strerror() : "Connection timed out");
 
205
                return ret;
 
206
        }
 
207
 
 
208
        snprintf(buf, buflen, "%.*s", ret, tmp);
 
209
 
 
210
        upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
 
211
        return ret;
 
212
}
 
213
 
 
214
 
97
215
static int krauler_command(const char *cmd, char *buf, size_t buflen)
98
216
{
99
217
        /*
119
237
 
120
238
        int     i;
121
239
 
122
 
        upsdebugx(3, "send: %.*s", strcspn(cmd, "\r"), cmd);
123
 
        
 
240
        upsdebugx(3, "send: %.*s", (int)strcspn(cmd, "\r"), cmd);
 
241
 
124
242
        for (i = 0; command[i].str; i++) {
125
243
                int     retry;
126
244
 
131
249
                for (retry = 0; retry < 10; retry++) {
132
250
                        int     ret;
133
251
 
134
 
                        ret = usb_get_string_simple(udev, command[i].index, buf, buflen);
 
252
                        if (langid_fix != -1) {
 
253
                                /* Apply langid_fix value */
 
254
                                ret = usb_get_string(udev, command[i].index, langid_fix, buf, buflen);
 
255
                        }
 
256
                        else {
 
257
                                ret = usb_get_string_simple(udev, command[i].index, buf, buflen);
 
258
                        }
135
259
 
136
260
                        if (ret <= 0) {
137
261
                                upsdebugx(3, "read: %s", ret ? usb_strerror() : "timeout");
138
262
                                return ret;
139
263
                        }
140
264
 
 
265
                        /* this may serve in the future */
 
266
                        upsdebugx(1, "received %d (%d)", ret, buf[0]);
 
267
 
 
268
                        if (langid_fix != -1) {
 
269
                                /* Limit this check, at least for now */
 
270
                                /* Invalid receive size - message corrupted */
 
271
                                if (ret != buf[0]) 
 
272
                                {
 
273
                                        upsdebugx(1, "size mismatch: %d / %d", ret, buf[0]);
 
274
                                        continue;
 
275
                                }
 
276
 
 
277
                                /* Simple unicode -> ASCII inplace conversion
 
278
                                 * FIXME: this code is at least shared with mge-shut/libshut
 
279
                                 * Create a common function? */
 
280
                                unsigned int di, si, size = buf[0];
 
281
                                for (di = 0, si = 2; si < size; si += 2) {
 
282
                                        if (di >= (buflen - 1))
 
283
                                                break;
 
284
 
 
285
                                        if (buf[si + 1]) /* high byte */
 
286
                                                buf[di++] = '?';
 
287
                                        else
 
288
                                                buf[di++] = buf[si];
 
289
                                }
 
290
                                buf[di] = 0;
 
291
                                ret = di;
 
292
                        }
 
293
 
141
294
                        /* "UPS No Ack" has a special meaning */
142
295
                        if (!strcasecmp(buf, "UPS No Ack")) {
 
296
                                upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
143
297
                                continue;
144
298
                        }
145
299
 
146
300
                        /* Replace the first byte of what we received with the correct one */
147
301
                        buf[0] = command[i].prefix;
148
302
 
 
303
                        upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
149
304
                        return ret;
150
305
                }
151
306
 
152
 
                upsdebugx(3, "read: %.*s", strcspn(buf, "\r"), buf);
153
307
                return 0;
154
308
        }
155
309
 
156
310
        /* echo the unknown command back */
157
 
        upsdebugx(3, "read: %.*s", strcspn(cmd, "\r"), cmd);
 
311
        upsdebugx(3, "read: %.*s", (int)strcspn(cmd, "\r"), cmd);
158
312
        return snprintf(buf, buflen, "%s", cmd);
159
313
}
160
314
 
161
315
 
 
316
static void *cypress_subdriver(void)
 
317
{
 
318
        subdriver_command = &cypress_command;
 
319
        return NULL;
 
320
}
 
321
 
 
322
 
 
323
static void *ippon_subdriver(void)
 
324
{
 
325
        subdriver_command = &ippon_command;
 
326
        return NULL;
 
327
}
 
328
 
 
329
 
 
330
static void *krauler_subdriver(void)
 
331
{
 
332
        subdriver_command = &krauler_command;
 
333
        return NULL;
 
334
}
 
335
 
 
336
 
162
337
static void *phoenix_subdriver(void)
163
338
{
164
339
        subdriver_command = &phoenix_command;
166
341
}
167
342
 
168
343
 
169
 
static void *krauler_subdriver(void)
170
 
{
171
 
        subdriver_command = &krauler_command;
172
 
        return NULL;
173
 
}
174
 
 
175
 
 
176
344
static usb_device_id_t blazer_usb_id[] = {
177
 
        { USB_DEVICE(0x05b8, 0x0000), &phoenix_subdriver },     /* Agiler UPS */
 
345
        { USB_DEVICE(0x05b8, 0x0000), &cypress_subdriver },     /* Agiler UPS */
178
346
        { USB_DEVICE(0x0001, 0x0000), &krauler_subdriver },     /* Krauler UP-M500VA */
179
347
        { USB_DEVICE(0xffff, 0x0000), &krauler_subdriver },     /* Ablerex 625L USB */
180
 
        { USB_DEVICE(0x0665, 0x5161), &phoenix_subdriver },     /* Belkin F6C1200-UNV */
181
 
        { USB_DEVICE(0x06da, 0x0003), &phoenix_subdriver },     /* Mustek Powermust */
182
 
        { USB_DEVICE(0x0f03, 0x0001), &phoenix_subdriver },     /* Unitek Alpha 1200Sx */
 
348
        { USB_DEVICE(0x0665, 0x5161), &cypress_subdriver },     /* Belkin F6C1200-UNV */
 
349
        { USB_DEVICE(0x06da, 0x0002), &cypress_subdriver },     /* Online Yunto YQ450 */
 
350
        { USB_DEVICE(0x06da, 0x0003), &ippon_subdriver },       /* Mustek Powermust */
 
351
        { USB_DEVICE(0x06da, 0x0004), &cypress_subdriver },     /* Phoenixtec Innova 3/1 T */
 
352
        { USB_DEVICE(0x06da, 0x0005), &cypress_subdriver },     /* Phoenixtec Innova RT */
 
353
        { USB_DEVICE(0x06da, 0x0201), &cypress_subdriver },     /* Phoenixtec Innova T */
 
354
        { USB_DEVICE(0x0f03, 0x0001), &cypress_subdriver },     /* Unitek Alpha 1200Sx */
 
355
        { USB_DEVICE(0x14f0, 0x00c9), &phoenix_subdriver },     /* GE EP series */
183
356
        /* end of list */
184
357
        {-1, -1, NULL}
185
358
};
236
409
 
237
410
        switch (ret)
238
411
        {
239
 
        case -EBUSY:
 
412
        case -EBUSY:            /* Device or resource busy */
240
413
                fatal_with_errno(EXIT_FAILURE, "Got disconnected by another driver");
241
414
 
242
 
        case -EPERM:
 
415
        case -EPERM:            /* Operation not permitted */
243
416
                fatal_with_errno(EXIT_FAILURE, "Permissions problem");
244
417
 
245
 
        case -EPIPE:
246
 
                if (!usb_clear_halt(udev, 0x81)) {
247
 
                        /* stall condition cleared */
 
418
        case -EPIPE:            /* Broken pipe */
 
419
                if (usb_clear_halt(udev, 0x81) == 0) {
 
420
                        upsdebugx(1, "Stall condition cleared");
248
421
                        break;
249
422
                }
250
 
        case -ENODEV:
251
 
        case -EACCES:
252
 
        case -EIO:
253
 
        case -ENOENT:
254
 
        case -ETIMEDOUT:
255
 
        default:
 
423
#ifdef ETIME
 
424
        case -ETIME:            /* Timer expired */
 
425
#endif
 
426
                if (usb_reset(udev) == 0) {
 
427
                        upsdebugx(1, "Device reset handled");
 
428
                }
 
429
        case -ENODEV:           /* No such device */
 
430
        case -EACCES:           /* Permission denied */
 
431
        case -EIO:              /* I/O error */
 
432
        case -ENXIO:            /* No such device or address */
 
433
        case -ENOENT:           /* No such file or directory */
256
434
                /* Uh oh, got to reconnect! */
257
435
                usb->close(udev);
258
436
                udev = NULL;
259
437
                break;
 
438
 
 
439
        case -ETIMEDOUT:        /* Connection timed out */
 
440
        case -EOVERFLOW:        /* Value too large for defined data type */
 
441
        case -EPROTO:           /* Protocol error */
 
442
        default:
 
443
                break;
260
444
        }
261
445
 
262
446
        return ret;
307
491
 
308
492
        addvar(VAR_VALUE, "bus", "Regular expression to match USB bus name");
309
493
 
 
494
        addvar(VAR_VALUE, "langid_fix", "Apply the language ID workaround to the krauler subdriver (0x409 or 0x4095)");
 
495
 
310
496
        blazer_makevartable();
311
497
}
312
498
 
318
504
                const char      *name;
319
505
                int             (*command)(const char *cmd, char *buf, size_t buflen);
320
506
        } subdriver[] = {
 
507
                { "cypress", &cypress_command },
321
508
                { "phoenix", &phoenix_command },
 
509
                { "ippon", &ippon_command },
322
510
                { "krauler", &krauler_command },
323
511
                { NULL }
324
512
        };
325
513
 
326
 
        int     ret;
 
514
        int     ret, langid;
 
515
        char    tbuf[255]; /* Some devices choke on size > 255 */
327
516
        char    *regex_array[6];
328
517
 
329
518
        char    *subdrv = getval("subdriver");
335
524
        regex_array[4] = getval("serial");
336
525
        regex_array[5] = getval("bus");
337
526
 
 
527
        /* check for language ID workaround (#1) */
 
528
        if (getval("langid_fix")) {
 
529
                /* skip "0x" prefix and set back to hexadecimal */
 
530
                if (sscanf(getval("langid_fix") + 2, "%x", &langid_fix) != 1) {
 
531
                        upslogx(LOG_NOTICE, "Error enabling language ID workaround");
 
532
                }
 
533
                else {
 
534
                        upsdebugx(2, "language ID workaround enabled (using '0x%x')", langid_fix);
 
535
                }
 
536
        }
 
537
 
338
538
        /* pick up the subdriver name if set explicitly */
339
539
        if (subdrv) {
340
540
                int     i;
369
569
                fatalx(EXIT_FAILURE, "invalid regular expression: %s", regex_array[ret]);
370
570
        }
371
571
 
 
572
 
372
573
        /* link the matchers */
373
574
        regex_matcher->next = &device_matcher;
374
575
 
375
576
        ret = usb->open(&udev, &usbdevice, regex_matcher, NULL);
376
577
        if (ret < 0) {
377
 
                fatalx(EXIT_FAILURE, 
 
578
                fatalx(EXIT_FAILURE,
378
579
                        "No supported devices found. Please check your device availability with 'lsusb'\n"
379
580
                        "and make sure you have an up-to-date version of NUT. If this does not help,\n"
380
581
                        "try running the driver with at least 'subdriver', 'vendorid' and 'productid'\n"
394
595
 
395
596
        /* link the matchers */
396
597
        reopen_matcher->next = regex_matcher;
 
598
 
 
599
        dstate_setinfo("ups.vendorid", "%04x", usbdevice.VendorID);
 
600
        dstate_setinfo("ups.productid", "%04x", usbdevice.ProductID);
 
601
 
 
602
        /* check for language ID workaround (#2) */
 
603
        if (langid_fix != -1) {
 
604
                /* Future improvement:
 
605
                 *   Asking for the zero'th index is special - it returns a string
 
606
                 *   descriptor that contains all the language IDs supported by the
 
607
                 *   device. Typically there aren't many - often only one. The
 
608
                 *   language IDs are 16 bit numbers, and they start at the third byte
 
609
                 *   in the descriptor. See USB 2.0 specification, section 9.6.7, for
 
610
                 *   more information on this.
 
611
                 * This should allow automatic application of the workaround */
 
612
                ret = usb_get_string(udev, 0, 0, tbuf, sizeof(tbuf));
 
613
                if (ret >= 4) {
 
614
                        langid = tbuf[2] | (tbuf[3] << 8);
 
615
                        upsdebugx(1, "First supported language ID: 0x%x (please report to the NUT maintainer!)", langid);
 
616
                }
 
617
        }
397
618
#endif
398
619
        blazer_initups();
399
620
}
402
623
void upsdrv_initinfo(void)
403
624
{
404
625
        blazer_initinfo();
405
 
 
406
 
        dstate_setinfo("ups.vendorid", "%04x", usbdevice.VendorID);
407
 
        dstate_setinfo("ups.productid", "%04x", usbdevice.ProductID);
408
626
}
409
627
 
410
628