Update initial source codes 70/88470/1 accepted/tizen_devbase_tools accepted/tools_devbase_tools accepted/tools_devbase_tools_legacy devel master release-20160930 accepted/tizen/devbase/tools/20190927.045004 accepted/tools/devbase/tools/20250527.103728 accepted/tools/devbase/tools/20250528.062206 accepted/tools/devbase/tools/legacy/20240422.110908 accepted/tools/devbase/tools/legacy/20240423.040742 accepted/tools/devbase/tools/legacy/20240424.050722 accepted/tools/devbase/tools/legacy/20250527.042451 submit/devel/20190730.074447 submit/devel/20190730.075528 submit/trunk/20190927.012842 submit/trunk/20191017.111201 submit/trunk/20191017.233826 submit/trunk/20191030.112603 submit/trunk/20191101.102136 submit/trunk/20200409.194520 submit/trunk/20200409.200220 submit/trunk/20200409.202020 submit/trunk/20201029.114030 submit/trunk/20201029.132130 upstream/4.3
authorDonghoon Shin <dhs.shin@samsung.com>
Mon, 19 Sep 2016 08:36:01 +0000 (17:36 +0900)
committerDonghoon Shin <dhs.shin@samsung.com>
Mon, 19 Sep 2016 08:36:01 +0000 (17:36 +0900)
Change-Id: I59bac2188ffbfe5a2ad2d9dcb33847aabfaffe44

47 files changed:
LICENSE [new file with mode: 0644]
Makefile [new file with mode: 0644]
Makefile-mac [new file with mode: 0644]
README.md [new file with mode: 0644]
USBaccess.cpp [new file with mode: 0644]
USBaccess.h [new file with mode: 0644]
USBaccessBasic.cpp [new file with mode: 0644]
USBaccessBasic.h [new file with mode: 0644]
circle.yml [new file with mode: 0644]
cleware.i [new file with mode: 0644]
clewarecontrol.1 [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/docs [new file with mode: 0644]
debian/files [new file with mode: 0644]
debian/rules [new file with mode: 0755]
debian/source/format [new file with mode: 0644]
error.cpp [new file with mode: 0644]
error.h [new file with mode: 0644]
example.pl [new file with mode: 0755]
example.py [new file with mode: 0755]
examples/Munin/cleware-munin.sh [new file with mode: 0644]
examples/Nagios/RCS/cleware_nagios_script,v [new file with mode: 0755]
examples/Nagios/cleware_nagios_script [new file with mode: 0755]
examples/Nagios/nagios.txt [new file with mode: 0644]
examples/Nagios/seealso.txt [new file with mode: 0644]
examples/RRD/add_measurement_to_rrd [new file with mode: 0755]
examples/RRD/draw_graph_from_rrd [new file with mode: 0755]
examples/RRD/make_rrd [new file with mode: 0755]
examples/RRD/rrd.txt [new file with mode: 0644]
examples/Watchdog/clewarewatchdog [new file with mode: 0755]
examples/Watchdog/watchdog.txt [new file with mode: 0644]
examples/ampel/ampel.txt [new file with mode: 0644]
examples/ampel/script.sh [new file with mode: 0755]
install-lib.pl [new file with mode: 0755]
install-lib.py [new file with mode: 0755]
mac-hidapi/hid.c [new file with mode: 0644]
mac-hidapi/hidapi.h [new file with mode: 0644]
main.cpp [new file with mode: 0644]
readme-mac.txt [new file with mode: 0644]
readme-perl.txt [new file with mode: 0644]
readme-python.txt [new file with mode: 0644]
readme.txt [new file with mode: 0644]
setup.py [new file with mode: 0644]
setup.py_CI [new file with mode: 0644]

diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..9591157
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,662 @@
+                    GNU AFFERO GENERAL PUBLIC LICENSE
+                       Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+  A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate.  Many developers of free software are heartened and
+encouraged by the resulting cooperation.  However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+  The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community.  It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server.  Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+  An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals.  This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU Affero General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Remote Network Interaction; Use with the GNU General Public License.
+
+  Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software.  This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero General Public License from time to time.  Such new versions
+will be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU Affero General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU Affero General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU Affero General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published
+    by the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source.  For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code.  There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+<http://www.gnu.org/licenses/>.
+
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..9f06861
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,51 @@
+# $Revision: 100 $
+VERSION=4.3
+
+DEBUG=-g -W -pedantic #-pg #-fprofile-arcs
+LDFLAGS+=`pkg-config --libs hidapi-hidraw`
+CXXFLAGS+=-O3 -Wall -DVERSION=\"$(VERSION)\" $(DEBUG) `pkg-config --cflags hidapi-hidraw`
+CFLAGS+=$(CXXFLAGS)
+
+OBJS=main.o USBaccessBasic.o USBaccess.o error.o
+
+all: clewarecontrol
+
+clewarecontrol: $(OBJS)
+       $(CXX) $(OBJS) $(LDFLAGS) -o clewarecontrol
+
+cleware_python:
+       swig -c++ -python cleware.i
+       python setup.py build_ext --inplace
+       ./install-lib.py
+
+cleware_perl:
+       swig -c++ -perl5 cleware.i
+       g++ -c `perl -MConfig -e 'print join(" ", @Config{qw(ccflags optimize cccdlflags)}, "-I$$Config{archlib}/CORE")'` cleware_wrap.cxx USBaccessBasic.cpp USBaccess.cpp
+       g++ `perl -MConfig -e 'print $$Config{lddlflags}'` cleware_wrap.o USBaccessBasic.o USBaccess.o -o cleware.so
+       ./install-lib.pl
+
+install: clewarecontrol
+       mkdir -p $(DESTDIR)$(PREFIX)/bin
+       cp clewarecontrol $(DESTDIR)$(PREFIX)/bin
+       mkdir -p $(DESTDIR)$(PREFIX)/share/man/man1
+       cp clewarecontrol.1 $(DESTDIR)$(PREFIX)/share/man/man1/clewarecontrol.1
+       gzip -9 $(DESTDIR)$(PREFIX)/share/man/man1/clewarecontrol.1
+
+uninstall: clean
+       rm -f $(DESTDIR)$(PREFIX)/bin/clewarecontrol
+       rm -f $(DESTDIR)$(PREFIX)/share/man/man1/clewarecontrol.1
+
+clean:
+       rm -rf $(OBJS) clewarecontrol core gmon.out *.da build cleware_wrap.cxx _cleware.so cleware.py* cleware.pm *.o cleware.so
+
+package: clean
+       # source package
+       rm -rf clewarecontrol-$(VERSION)*
+       mkdir clewarecontrol-$(VERSION)
+       cp -a *.c* *.h *.i *.pl *py readme*.txt clewarecontrol.1 Makefile LICENSE clewarecontrol-$(VERSION)
+       tar cf - examples --exclude=.svn  | tar xvf - -C clewarecontrol-$(VERSION)
+       tar czf clewarecontrol-$(VERSION).tgz clewarecontrol-$(VERSION)
+       rm -rf clewarecontrol-$(VERSION)
+
+stest:
+       cppcheck -v --enable=all --inconclusive -I. . 2> err.txt
diff --git a/Makefile-mac b/Makefile-mac
new file mode 100644 (file)
index 0000000..428e498
--- /dev/null
@@ -0,0 +1,39 @@
+# $Revision: 100 $
+VERSION=4.1
+
+DEBUG=-g -W -pedantic #-pg #-fprofile-arcs
+LDFLAGS+=-framework IOKit -framework CoreFoundation
+CXXFLAGS+=-O3 -Wall -DVERSION=\"$(VERSION)\" $(DEBUG)
+CFLAGS+=$(CXXFLAGS)
+
+OBJS=main.o USBaccessBasic.o USBaccess.o error.o mac-hidapi/hid.o
+
+all: clewarecontrol
+
+clewarecontrol: $(OBJS)
+       $(CXX) $(OBJS) $(LDFLAGS) -o clewarecontrol
+
+cleware_python:
+       swig -c++ -python cleware.i
+       python setup.py build_ext --inplace
+       ./install-lib.py
+
+cleware_perl:
+       swig -c++ -perl5 cleware.i
+       g++ -c `perl -MConfig -e 'print join(" ", @Config{qw(ccflags optimize cccdlflags)}, "-I$$Config{archlib}/CORE")'` cleware_wrap.cxx USBaccessBasic.cpp USBaccess.cpp
+       g++ `perl -MConfig -e 'print $$Config{lddlflags}'` cleware_wrap.o USBaccessBasic.o USBaccess.o -o cleware.so
+       ./install-lib.pl
+
+dmg: clewarecontrol
+       rm -rf macosx
+       mkdir -p macosx
+       cp clewarecontrol clewarecontrol.1 macosx/
+       cp readme-mac.txt macosx/
+       rm -f clewarecontrol-$(VERSION).dmg
+       hdiutil create -srcfolder macosx -volname "ClewareControl" -fs HFS+ -fsargs "-c c=64,a=16,e=16" -format UDRW -size 1024k clewarecontrol-$(VERSION).dmg
+
+clean:
+       rm -rf $(OBJS) clewarecontrol core gmon.out *.da build cleware_wrap.cxx _cleware.so cleware.py* cleware.pm *.o cleware.so
+
+check:
+       cppcheck -v --enable=all --inconclusive -I. . 2> err.txt
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..08fbde2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,168 @@
+CircleCI Status
+---------------
+
+[![Circle CI](https://circleci.com/gh/zoff99/clewarecontrol/tree/build_with_circleCI.svg?style=svg)](https://circleci.com/gh/zoff99/clewarecontrol/tree/build_with_circleCI)
+
+
+build instructions
+------------------
+Required libraries:
+       libhidapi-dev
+
+Since version 4.0 clewarecontrol uses this library to abstract the
+interfacing with the kernel. That way it may work on other OSes and new(er)
+kernel as well.
+
+If you get errors, try replacing -lhidapi by -lhidraw-libusb or hidapi-hidraw.
+If you still get errors, contact me.
+
+
+Installation:
+       make install
+
+
+usage
+-----
+Please see the man-page for help on how to use it:
+       make clewarecontrol
+
+or run the program with the -h switch:
+       clewarecontrol -h
+
+Please also check the website for tips and help.
+
+
+devices
+-------
+- temperature sensor
+       clewarecontrol -rt
+
+- humidity sensor
+  This device needs to be "started" first, then you can read sensor readings
+       clewarecontrol -ag -rh
+
+- 2 channel AD converter (analog to digital)
+  First you need to know what it range it works: 5v, 13v or 24v
+  then you must select the channel to read from - the device has 2 channels
+  after selecting the channel, you can keep reading
+       clewarecontrol -ai x        where x is 0 or 1 (selects channel)
+       clewarecontrol -ra y        where y is 0 voor 5v, 1 for 13v, etc.
+- Ampel ("Switch1 (8)")
+  The traffic light is, from clewarecontrol seen, a device with 3 switches in
+  it that can be individiually switched on and off
+       clewarecontrol -as x y      where x is 0, 1 or 2 (0=red, 2=green) and
+                                    y is 0 or 1 (0 is off)
+
+- IO16 ("Contact 00 device (48)")
+  The IO16 is a 16 port I/O interface. You can configure each pin to be either
+  input or output. This setting is stored in an eprom so that a pin cannot
+  become accidently output while you expected an input.
+  Set the direction with:
+       clewarecontrol -ad x        where x is a hex value representing a 1
+                                    or 0 selecting the direction
+  After that you can set the output pins to 1 or 0 with:
+       clewarecontrol -am x        where is a hex value
+
+- Luminus
+  This is in fact an AD converter with integrated hardware which measures the
+  amount of light. It has 1 chnanel, so you don't need to select it (like the
+  generic ADC). Reading values (in version 2.5) can be perfomed like his:
+       clewarecontrol -ra 0
+  This gives a value between 0 and 5. I (developer of this Linux program)
+  need to buy a lux meter to scale this correctly.
+
+
+- USB-cutter
+  This is a device which is at its heart a switch like the other switches.
+  To use it, you need to start it:
+       clewarecontrol -ag
+  then, you can toggle the USB status like this:
+       clewarecontrol -as 0 1      this will "cut" the USB device (switching
+                                   it off)
+       clewarecontrol -as 0 0      this will enable the USB device again(!)
+  indeed, the logic is inverted.
+
+
+-mintrig / -maxtrig
+-------------------
+Run the program with -c 0 so that it keeps running forever (unless you want to
+have it monitor the value for a shorter time).
+Also start it with -F so that it runs in the background.
+Then set the -mintrig or -maxtrig switches.
+As the last parameter, set the sensor to monitor: -rh (humidity), -rt
+(temperature), etc.
+For example:
+       clewarecontrol -c 0 -maxtrig 0.5 ./myscript.sh -ra 0
+If the ADC tells us that the voltage is over 0.5 volts, then "myscript.sh" is
+invoked. As a parameter, the script will get the measured value.
+
+
+I would be delighted if you share your experiences with me!
+
+
+python library
+--------------
+please see readme-python.txt for details on how to create and use the python
+library.
+
+
+perl library
+--------------
+please see readme-perl.txt for details on how to create and use the perl
+library.
+
+
+problems
+--------
+If you encounter any problems when using clewarecontrol with Cleware devices,
+DO NOT contact Cleware but please contact me: folkert@vanheusden.com
+
+Of course you can always write me when you have questions/suggestions/etc.
+ folkert@vanheusden.com
+
+
+FAQ
+---
+Q1. Values retrieved are invalid
+A1. Occasionally the values retrieved are invalid. E.g. a temperature of 170
+    degrees and such. In that case you can reset the device (might need to
+    reset it multiple times!) and then it'll work
+
+Q2. It does not compile on SuSE Enterprise Linux 10
+A2. Insert in file USBaccessBasic.c at line 17 (that is BEFORE the line
+    including usbdevice_fs.h!) the following line:
+       #define __user
+
+Q3. clewarecontrol -l doesn't list any devices
+A3. The Cleware USB library expects the following files to exist:
+       crw-rw-rw- 1 root root 180,  96 May  9  2005 /dev/usb/hiddev0
+       crw-rw-rw- 1 root root 180,  97 May  9  2005 /dev/usb/hiddev1
+       ...
+       crw-rw-rw- 1 root root 180, 110 May  9  2005 /dev/usb/hiddev14
+       crw-rw-rw- 1 root root 180, 111 May  9  2005 /dev/usb/hiddev15
+
+    Since version 1.2 you can use -p to select a different path, eg.:
+       clewarecontrol -p /dev -l
+
+    Make sure the user you're running clewarecontrol from has enought rights
+    to access the devices. For starters, to see if it works at all, run it as
+    root.
+
+Q4. clewarecontrol still can't find any devices
+A4. If that still does not give any output then please e-mail me the output of
+    the following commands:
+       uname -a
+       lsusb
+       lsmod
+       strace clewarecontrol -l
+       ps -deaf | grep udev
+       find /dev -name hiddev\*
+
+    Please also tell me what distribution (e.g. redhat/suse/ubuntu) and what
+    version you're using
+
+
+Regards,
+
+Folkert van Heusden
diff --git a/USBaccess.cpp b/USBaccess.cpp
new file mode 100644 (file)
index 0000000..708596f
--- /dev/null
@@ -0,0 +1,1189 @@
+// Basic class implementation for access to USB HID devices\r
+//\r
+// (C) 2001 Copyright Cleware GmbH\r
+// All rights reserved\r
+//\r
+// History:\r
+// 05.01.01    ws      Initial coding\r
+\r
+#include <stdlib.h>\r
+#include <unistd.h>\r
+#include <stdio.h>\r
+#include "USBaccess.h"\r
+#include "USBaccessBasic.h"\r
+\r
+\r
+CUSBaccess::CUSBaccess() {\r
+       cwInitCleware() ;\r
+       }\r
+\r
+CUSBaccess::~CUSBaccess() {\r
+       }\r
+\r
+\r
+// returns number of found Cleware devices\r
+int\r
+CUSBaccess::OpenCleware() {\r
+       int rval = cwOpenCleware(NULL) ;\r
+\r
+       return rval ;\r
+       }\r
+\r
+int\r
+CUSBaccess::Recover(int devNum) {\r
+       int rval = cwRecover(devNum) ;\r
+\r
+       return rval ;\r
+       }\r
+\r
+// return true if ok, else false\r
+int\r
+CUSBaccess::CloseCleware() {\r
+       int rval = 1 ;\r
+       \r
+       cwCloseCleware() ;\r
+\r
+       return rval ;\r
+       }\r
+\r
+HANDLE\r
+CUSBaccess::GetHandle(int deviceNo) { \r
+       return cwGetHandle(deviceNo) ; \r
+       }\r
+\r
+int \r
+CUSBaccess::GetVersion(int deviceNo) { \r
+       return cwGetVersion(deviceNo) ; \r
+       }\r
+\r
+int \r
+CUSBaccess::GetUSBType(int deviceNo) { \r
+       int devType = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+       int devVersion = cwGetVersion(deviceNo) ;\r
+       if (devType == CONTACT00_DEVICE && devVersion <= 12 && devVersion > 5) {\r
+               // this may be an early switch3/4 build on base of contact HW - adjust the ID\r
+               int switchCount = 0 ;\r
+               for (int autoCnt=4 ; autoCnt > 0 ; autoCnt--) {\r
+                       const int bufSize = 6 ;\r
+                       unsigned char buf[bufSize] = { 0, 0, 0, 0, 0, 0 } ;\r
+                       int seqNumber = SyncDevice(deviceNo, 0xffff) ;\r
+                       Sleep(20) ;\r
+\r
+                       for (int securityCnt=50 ; switchCount == 0 && seqNumber != 0 && securityCnt > 0 ; securityCnt--) {\r
+                               if (GetValue(deviceNo, buf, bufSize)) {\r
+                                       if (buf[1] == seqNumber) {\r
+                                               switchCount = buf[0] & 0x7f ;\r
+                                               break ;\r
+                                               }\r
+                                       }\r
+                               else {\r
+                                       securityCnt /= 10 ;             // don't wait too long if GetValue failed\r
+                                       Sleep(20) ;\r
+                                       }\r
+                               }\r
+                       }\r
+               if (switchCount > 0 && switchCount <= 8)\r
+                       devType = SWITCHX_DEVICE ;\r
+               }\r
+       return devType ;\r
+       }\r
+\r
+int     \r
+CUSBaccess::GetSerialNumber(int deviceNo) { \r
+       return cwGetSerialNumber(deviceNo) ; \r
+       }\r
+\r
+\r
+\r
+// returns 1 if ok or 0 in case of an error\r
+int            \r
+CUSBaccess::GetValue(int deviceNo, unsigned char *buf, int bufsize) {\r
+       int rval = cwGetValue(deviceNo, buf, bufsize) ;\r
+\r
+       return rval ;\r
+       }\r
+\r
+\r
+int \r
+CUSBaccess::SetValue(int deviceNo, unsigned char *buf, int bufsize) {\r
+       int rval = cwSetValue(deviceNo, buf, bufsize) ;\r
+       \r
+       return rval ;\r
+       }\r
+\r
+int \r
+CUSBaccess::SetLED(int deviceNo, enum LED_IDs Led, int value) {\r
+       unsigned char s[6] ;\r
+       int rval = 0 ;\r
+       \r
+       USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+       int version = cwGetVersion(deviceNo) ;\r
+\r
+       if (devType == LED_DEVICE && version <= 10) {\r
+               s[0] = Led ;\r
+               s[1] = value ;\r
+               rval = SetValue(deviceNo, s, 2) ;\r
+               }\r
+       else if (devType == TEMPERATURE2_DEVICE || devType == HUMIDITY1_DEVICE) {\r
+               s[0] = 0 ;\r
+               s[1] = Led ;\r
+               s[2] = value ;\r
+               s[3] = 0 ;\r
+               rval = SetValue(deviceNo, s, 4) ;\r
+               }\r
+       else if (devType == ENCODER01_DEVICE) {\r
+               s[0] = 0 ;\r
+               s[1] = Led ;\r
+               s[2] = value ;\r
+               s[3] = 0 ;\r
+               s[4] = 0 ;\r
+               s[5] = 0 ;\r
+               rval = SetValue(deviceNo, s, 6) ;\r
+               }\r
+       else if ((devType == CONTACT00_DEVICE && version > 6) || devType == KEYC01_DEVICE || devType == KEYC16_DEVICE || devType == WATCHDOGXP_DEVICE || devType == SWITCHX_DEVICE) {           // 5 bytes to send\r
+               s[0] = 0 ;\r
+               s[1] = Led ;\r
+               s[2] = value ;\r
+               s[3] = 0 ;\r
+               s[4] = 0 ;\r
+               rval = SetValue(deviceNo, s, 5) ;\r
+               }\r
+       else {\r
+               s[0] = 0 ;\r
+               s[1] = Led ;\r
+               s[2] = value ;\r
+               rval = SetValue(deviceNo, s, 3) ;\r
+               }\r
+\r
+       return rval ;\r
+       }\r
+\r
+int \r
+CUSBaccess::SetSwitch(int deviceNo, enum SWITCH_IDs Switch, int On) {\r
+       unsigned char s[6] ;\r
+       int rval = 0 ;\r
+       int version = cwGetVersion(deviceNo) ;\r
+       \r
+       if (Switch < SWITCH_0 || Switch > SWITCH_15)\r
+               return -1 ;\r
+\r
+       USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+       if (devType == SWITCH1_DEVICE || devType == AUTORESET_DEVICE || devType == WATCHDOG_DEVICE) {\r
+               s[0] = 0 ;\r
+               s[1] = Switch ;\r
+               if (version < 4)        // old version do not invert\r
+                       s[2] = !On ;\r
+               else\r
+                       s[2] = On ;\r
+               rval = SetValue(deviceNo, s, 3) ;\r
+               if (rval && Switch == SWITCH_0) {                       // set LED for first switch\r
+                       if (On) {\r
+                               SetLED(deviceNo, LED_0, 0) ;    // USB Switch will invert LED\r
+                               SetLED(deviceNo, LED_1, 15) ;\r
+                               }\r
+                       else {\r
+                               SetLED(deviceNo, LED_0, 15) ;\r
+                               SetLED(deviceNo, LED_1, 0) ;\r
+                               }\r
+                       }\r
+               }\r
+       else if (devType == SWITCHX_DEVICE || devType == WATCHDOGXP_DEVICE || (devType == CONTACT00_DEVICE && version > 6)) {           // 5 bytes to send\r
+               int mask = 1 << (Switch - SWITCH_0) ;           // setup mask\r
+               int data = 0 ;\r
+               if (On)\r
+                       data = mask ;\r
+// LINUX sign bit problem\r
+               s[0] = 3 << 4 ;\r
+               if (data & 0x8000)\r
+                       s[0] |= 0x08 ;\r
+               if (data & 0x80)\r
+                       s[0] |= 0x04 ;\r
+               if (mask & 0x8000)\r
+                       s[0] |= 0x02 ;\r
+               if (mask & 0x80)\r
+                       s[0] |= 0x01 ;\r
+               s[1] = (unsigned char)(data >> 8)  & 0x7f ;\r
+               s[2] = (unsigned char)(data & 0xff) & 0x7f  ;\r
+               s[3] = (unsigned char)(mask >> 8)  & 0x7f ;\r
+               s[4] = (unsigned char)(mask & 0xff) & 0x7f  ;\r
+/*     old code, may cause Linux sign problem
+               if (GetHWversion(deviceNo) == 0)
+               s[0] = 3 ;\r
+               else
+                       s[0] = ContactWrite ;\r
+               s[1] = data >> 8 ;\r
+               s[2] = data & 0xff ;\r
+               s[3] = mask >> 8 ;\r
+               s[4] = mask & 0xff ;\r
+*/
+               rval = SetValue(deviceNo, s, 5) ;\r
+               }\r
+       else if (devType == ENCODER01_DEVICE) {\r
+               s[0] = 0 ;\r
+               s[1] = Switch ;\r
+               s[2] = On ;\r
+               s[3] = 0 ;\r
+               s[4] = 0 ;\r
+               s[5] = 0 ;\r
+               rval = SetValue(deviceNo, s, 6) ;\r
+               }\r
+       else if (devType == COUNTER00_DEVICE) {\r
+               s[0] = 0 ;\r
+               s[1] = Switch ;\r
+               s[2] = On ;\r
+               rval = SetValue(deviceNo, s, 3) ;\r
+               }\r
+       else\r
+               rval = -1 ;\r
+\r
+       return rval ;\r
+       }\r
+\r
+int            // 0=error, else=ok \r
+CUSBaccess::GetSwitchConfig(int deviceNo, int *switchCount, int *buttonAvailable) {\r
+       const int bufSize = 6 ;\r
+       unsigned char buf[bufSize] = { 0, 0, 0, 0, 0, 0 } ;\r
+       int ok = 0 ;\r
+       USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+       int version = cwGetVersion(deviceNo) ;\r
+\r
+       if ((devType == CONTACT00_DEVICE && version >= 5) || devType == SWITCHX_DEVICE || devType == WATCHDOGXP_DEVICE) {\r
+               *switchCount = 0 ;\r
+               for (int autoCnt=4 ; autoCnt > 0 ; autoCnt--) {\r
+                       int seqNumber = SyncDevice(deviceNo, 0xffff) ;\r
+                       Sleep(20) ;\r
+\r
+                       for (int securityCnt=50 ; seqNumber != 0 && securityCnt > 0 ; securityCnt--) {\r
+                               if (GetValue(deviceNo, buf, bufSize)) {\r
+                                       if (buf[1] == seqNumber) {\r
+                                               ok = 1 ;\r
+                                               *switchCount = buf[0] & 0x7f ;\r
+                                               break ;\r
+                                               }\r
+                                       }\r
+                               else {\r
+                                       securityCnt /= 10 ;             // don't wait too long if GetValue failed\r
+                                       Sleep(20) ;\r
+                                       }\r
+                               }\r
+                       if (ok >= 0)\r
+                               break ;\r
+                       }\r
+               if (buttonAvailable)\r
+                       *buttonAvailable = 0 ;\r
+               return ok ;\r
+               }\r
+\r
+       if (devType == COUNTER00_DEVICE) {\r
+               *switchCount = 2 ;\r
+               if (buttonAvailable)\r
+                       *buttonAvailable = 0 ;\r
+               return ok ;\r
+               }\r
+\r
+       if (    devType == SWITCH1_DEVICE \r
+                || devType == AUTORESET_DEVICE \r
+                || devType == WATCHDOG_DEVICE \r
+                || devType == F4_DEVICE) {\r
+               *switchCount = 1 ;\r
+               *buttonAvailable = 0 ;\r
+               if (version >= 10) {    \r
+                       if (ok = GetValue(deviceNo, buf, bufSize) && (buf[0] & 0x80)) {\r
+                               *switchCount = 1 ;\r
+                               if (buf[0] & 0x02)\r
+                                       *switchCount = 2 ;\r
+                               if (buf[0] & 0x08)\r
+                                       *switchCount = 3 ;\r
+                               if (buf[0] & 0x20) {\r
+                                       if (*switchCount == 3)\r
+                                               *switchCount = 4 ;                              // only single switches may have a start button\r
+                                       else\r
+                                               *buttonAvailable = 1 ;\r
+                                       }\r
+                               }\r
+                       }\r
+               else\r
+                       ok = 1 ;\r
+               }\r
+\r
+       return ok ;\r
+       }\r
+\r
+int            // On 0=off, 1=on, -1=error      \r
+CUSBaccess::GetSwitch(int deviceNo, enum SWITCH_IDs Switch) {\r
+       const int bufSize = 6 ;\r
+       unsigned char buf[bufSize] ;\r
+       int ok = 0 ;\r
+       USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+\r
+       if (            devType != SWITCH1_DEVICE \r
+                        && devType != AUTORESET_DEVICE \r
+                        && devType != WATCHDOG_DEVICE \r
+                        && devType != WATCHDOGXP_DEVICE \r
+                        && devType != F4_DEVICE \r
+                        && devType != SWITCHX_DEVICE \r
+                        && devType != CONTACT00_DEVICE \r
+                        && devType != COUNTER00_DEVICE \r
+                        && devType != ENCODER01_DEVICE)\r
+               return -1 ;\r
+\r
+       if (Switch < SWITCH_0 || Switch > SWITCH_15)\r
+               return -1 ;\r
+\r
+       int version = cwGetVersion(deviceNo) ;\r
+\r
+       if ((devType == CONTACT00_DEVICE && version > 6) || devType == SWITCHX_DEVICE || devType == WATCHDOGXP_DEVICE) {                // 5 bytes to send\r
+               unsigned long int mask = 1 << (Switch - SWITCH_0) ;             // setup mask\r
+               unsigned long int data = 0 ;\r
+               ok = GetMultiSwitch(deviceNo, &mask, &data, 0) ;        // mask is change ,ask on return\r
+               mask = 1 << (Switch - SWITCH_0) ;               // setup mask\r
+               if (ok >= 0)\r
+                       ok = (data & mask) ? 1 : 0 ;\r
+               }\r
+\r
+       else if (1 || version < 10) {                                   // else only if in separate thread\r
+               if (GetValue(deviceNo, buf, bufSize)) {\r
+                       int mask = 1 << ((Switch - SWITCH_0) * 2) ;\r
+                       if (version >= 10 || devType == CONTACT00_DEVICE || devType == COUNTER00_DEVICE || devType == F4_DEVICE)\r
+                               ok = (buf[0] & mask) ? 1 : 0 ;\r
+                       else    // old switch\r
+                               ok = (buf[2] & mask) ? 1 : 0 ;\r
+                       }\r
+               else\r
+                       ok = -1 ;       // getvalue failed - may be disconnected\r
+\r
+               if (ok >= 0 && version < 4 && devType != CONTACT00_DEVICE && devType != COUNTER00_DEVICE&& devType != F4_DEVICE)\r
+                       ok = !ok ;\r
+               }\r
+       else {          // new version - ask for online count to get a fast answer (use this only if in separate thread)\r
+               static int sequenceNumber = 1 ;\r
+\r
+               buf[0] = GetInfo ;\r
+               buf[1] = OnlineCount ;\r
+               buf[2] = sequenceNumber ;\r
+               SetValue(deviceNo, buf, 3) ;\r
+               for (int timeout=25 ; timeout > 0 ; timeout--) {\r
+                       Sleep(25) ;\r
+                       if (GetValue(deviceNo, buf, bufSize)) {\r
+                               if ((buf[0] & 0x80) == 0)       // valid bit\r
+                                       continue ;\r
+                               if (buf[1] != ( (sequenceNumber & 0x1f) << 3 ) + OnlineCount)\r
+                                       continue ;\r
+                               ok = buf[0] & 1 ;\r
+                               break ;\r
+                               }\r
+                       }\r
+\r
+               sequenceNumber = (++sequenceNumber) & 0x1f ;\r
+               }\r
+\r
+       return ok ;\r
+       }\r
+\r
+int            // On 0=off, 1=on, -1=error      ; the seqNum is generated by the Start command.\r
+CUSBaccess::GetSeqSwitch(int deviceNo, enum SWITCH_IDs Switch, int seqNumber) {\r
+       const int bufSize = 6 ;\r
+       unsigned char buf[bufSize] ;\r
+       int ok = 0 ;\r
+       USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+\r
+       if (            devType != SWITCH1_DEVICE \r
+                        && devType != AUTORESET_DEVICE \r
+                        && devType != WATCHDOG_DEVICE \r
+                        && devType != F4_DEVICE \r
+                        && devType != CONTACT00_DEVICE \r
+                        && devType != SWITCHX_DEVICE \r
+                        && devType != COUNTER00_DEVICE \r
+                        && devType != ENCODER01_DEVICE)\r
+               return -1 ;\r
+\r
+       if (Switch < SWITCH_0 || Switch > SWITCH_15)\r
+               return -1 ;\r
+\r
+       int version = cwGetVersion(deviceNo) ;\r
+       if (version < 20 && devType != CONTACT00_DEVICE && devType != SWITCHX_DEVICE && devType != COUNTER00_DEVICE && devType != F4_DEVICE)\r
+               return -1 ;\r
+\r
+       if (seqNumber == 0)                     // do this internally\r
+               seqNumber = StartDevice(deviceNo) ;\r
+\r
+       buf[1] = 0 ;\r
+       for (int securityCnt=20 ; buf[1] != seqNumber && securityCnt > 0 ; securityCnt--) {\r
+               if (GetValue(deviceNo, buf, bufSize)) {\r
+                       int mask = 1 << ((Switch - SWITCH_0) * 2) ;\r
+                       ok = (buf[0] & mask) ? 1 : 0 ;\r
+                       }\r
+               else {\r
+                       ok = -1 ;       // getvalue failed - may be disconnected\r
+                       break ;\r
+                       }\r
+               }\r
+\r
+       return ok ;\r
+       }\r
+\r
+int            // rval seqNum = ok, -1 = error  \r
+CUSBaccess::GetMultiSwitch(int deviceNo, unsigned long int *mask, unsigned long int *value, int seqNumber) {\r
+       unsigned char buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 } ;\r
+       int bufSize ;\r
+       int ok = -1 ;\r
+       int automatic = 0 ;\r
+\r
+       USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+       int version = cwGetVersion(deviceNo) ;\r
+\r
+       if (devType == KEYC16_DEVICE) \r
+               bufSize = 8 ;\r
+       else if (devType == CONTACT00_DEVICE || devType == KEYC01_DEVICE || devType == SWITCHX_DEVICE || devType == WATCHDOGXP_DEVICE) {\r
+               if (version < 5)\r
+                       return -1 ;\r
+               bufSize = 6 ;\r
+               }\r
+       else\r
+               return -1 ;\r
+\r
+       if (value == 0)\r
+               return -1 ;\r
+\r
+       if (seqNumber == 0)                     // do this internally\r
+               automatic = 1 ;\r
+\r
+       int readMask = 0 ;\r
+       if (mask)\r
+               readMask = *mask ;\r
+       if (readMask == 0)\r
+               readMask = 0xffff ;             // get every single bit!!\r
+\r
+       for (int autoCnt=4 ; autoCnt > 0 ; autoCnt--) {\r
+               if (automatic) {\r
+                       seqNumber = SyncDevice(deviceNo, readMask) ;\r
+                       Sleep(20) ;\r
+                       }\r
+\r
+               for (int securityCnt=50 ; seqNumber != 0 && securityCnt > 0 ; securityCnt--) {\r
+                       if (GetValue(deviceNo, buf, bufSize)) {\r
+                               if (mask != 0)\r
+                                       *mask =  (buf[2] << 8) + buf[3] ;\r
+                               unsigned long int v = (buf[4] << 8) + buf[5] ;\r
+                               if (version < 7 && devType != KEYC16_DEVICE && devType != KEYC01_DEVICE)\r
+                                       *value = 0xffff & ~v ;\r
+                               else\r
+                                       *value = v ;\r
+                               if (buf[1] == seqNumber) {\r
+                                       ok = seqNumber ;\r
+                                       break ;\r
+                                       }\r
+                       //      Sleep(50) ;                             don't sleep - we just killing the USB fifo\r
+                               }\r
+                       else {\r
+                               securityCnt /= 10 ;             // don't wait too long if GetValue failed\r
+                               Sleep(20) ;\r
+                               }\r
+                       }\r
+               if (ok >= 0 || automatic == 0)\r
+                       break ;\r
+               }\r
+\r
+       return ok ;\r
+       }\r
+\r
+int            // On 0=ok, -1=error     \r
+CUSBaccess::SetMultiSwitch(int deviceNo, unsigned long int value) {\r
+       const int bufSize = 5 ;\r
+       unsigned char buf[bufSize] ;\r
+       int ok = -1 ;\r
+       USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+\r
+       if (devType != CONTACT00_DEVICE && devType != SWITCHX_DEVICE && devType != WATCHDOGXP_DEVICE)\r
+               return -1 ;\r
+\r
+       int version = cwGetVersion(deviceNo) ;\r
+       if (version < 5)\r
+               return -1 ;\r
+\r
+/* orginal\r
+       buf[0] = 3 ;\r
+       buf[1] = (unsigned char)(value >> 8) ;\r
+       buf[2] = (unsigned char)(value & 0xff) ;\r
+       buf[3] = 0xff ;\r
+       buf[4] = 0xff ;\r
+*/\r
+// LINUX sign bit problem\r
+       buf[0] = 3 << 4 ;\r
+       if (value & 0x8000)\r
+               buf[0] |= 0x08 ;\r
+       if (value & 0x80)\r
+               buf[0] |= 0x04 ;\r
+       buf[0] |= 3 ;   // mask bits\r
+       buf[1] = (unsigned char)(value >> 8)  & 0x7f ;\r
+       buf[2] = (unsigned char)(value & 0xff) & 0x7f  ;\r
+       buf[3] = 0x7f ;\r
+       buf[4] = 0x7f ;\r
+\r
+       if (SetValue(deviceNo, buf, version > 6 ? 5 : 3))\r
+               ok = 0 ;\r
+\r
+       return ok ;\r
+       }\r
+\r
+int            // On 0=ok, -1=error     \r
+CUSBaccess::SetMultiConfig(int deviceNo, unsigned long int directions) {       // 1=input, 0=output\r
+       const int bufSize = 5 ;\r
+       unsigned char buf[bufSize] ;\r
+       int ok = -1 ;\r
+       USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+\r
+       if (devType != CONTACT00_DEVICE && devType != SWITCHX_DEVICE && devType != WATCHDOGXP_DEVICE) \r
+               return -1 ;\r
+\r
+       int version = cwGetVersion(deviceNo) ;\r
+       if (version < 5)\r
+               return -1 ;\r
+\r
+/* orginal\r
+       if (version < 10)\r
+               buf[0] = KeepCalm ;                     // dirty old code\r
+       else\r
+               buf[0] = Configure ;\r
+       buf[1] = (unsigned char)(directions >> 8) ;\r
+       buf[2] = (unsigned char)(directions & 0xff) ;\r
+       buf[3] = 0 ;\r
+       buf[4] = 0 ;\r
+*/\r
+// LINUX sign bit problem\r
+       if (version < 10)\r
+               buf[0] = 4 << 4 ;               // dirty old code\r
+       else\r
+               buf[0] = 7 << 4 ;\r
+       if (directions & 0x8000)\r
+               buf[0] |= 0x08 ;\r
+       if (directions & 0x80)\r
+               buf[0] |= 0x04 ;\r
+       buf[1] = (unsigned char)(directions >> 8)  & 0x7f ;\r
+       buf[2] = (unsigned char)(directions & 0xff) & 0x7f  ;\r
+       buf[3] = 0 ;\r
+       buf[4] = 0 ;\r
+\r
+       if (SetValue(deviceNo, buf, version > 6 ? 5 : 3))\r
+               ok = 0 ;\r
+\r
+       return ok ;\r
+       }\r
+\r
+int            // // return value of counter (0 or 1 for USB-IO16) or -1 in case of an error\r
+CUSBaccess::GetCounter(int deviceNo, enum COUNTER_IDs counterID) {\r
+       const int bufSize = 6 ;\r
+       unsigned char buf[bufSize] ;\r
+       int rval = -1 ;\r
+       int automatic = 0 ;\r
+       static int sequenceNumber = 1 ;\r
+       int sendlen = bufSize ;\r
+       int isIO16 = false ;\r
+\r
+// original\r
+//     sequenceNumber = (++sequenceNumber) & 0xff ;\r
+       if (++sequenceNumber > 0x7f)    // LINUX sign bit problem\r
+               sequenceNumber = 1 ;\r
+\r
+       USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+       int version = cwGetVersion(deviceNo) ;\r
+\r
+       if (devType == CONTACT00_DEVICE) {\r
+               sendlen = 5 ;\r
+               if (version >= 6)\r
+                       isIO16 = true ;\r
+               }\r
+       else if (devType == COUNTER00_DEVICE) \r
+               sendlen = 3 ;\r
+       else\r
+               return -1 ;\r
+\r
+       for (int autoCnt=4 ; autoCnt > 0 ; autoCnt--) {\r
+               buf[0] = CUSBaccess::GetInfo ;\r
+               buf[1] = sequenceNumber ;\r
+               buf[2] = 0 ;\r
+               buf[3] = 0 ;\r
+               buf[4] = 0 ;\r
+\r
+               if (!SetValue(deviceNo, buf, sendlen)) {\r
+                       Sleep(50) ;\r
+                       continue ;\r
+                       }\r
+               Sleep(20) ;\r
+\r
+               buf[1] = 0 ;\r
+               for (int securityCnt=50 ; securityCnt > 0 ; securityCnt--) {\r
+                       if (GetValue(deviceNo, buf, bufSize)) {\r
+                               if (isIO16 && buf[0] != 0xff) {                 // 0xff indicates that the counters are prepared \r
+                                       Sleep(10) ;\r
+                                       continue ;\r
+                                       }\r
+                               if (buf[1] != sequenceNumber) {\r
+                                       Sleep(10) ;\r
+                                       continue ;\r
+                                       }\r
+                               if (!isIO16)\r
+                                       rval = (buf[2] << 24) + (buf[3] << 16) + (buf[4] << 8) + buf[5] ;\r
+                               else {\r
+                                       if (counterID == 0)\r
+                                               rval = (buf[2] << 8) + buf[3] ;\r
+                                       else\r
+                                               rval = (buf[4] << 8) + buf[5] ;\r
+                                       }\r
+                               break ;\r
+                       //      Sleep(50) ;                             don't sleep - we just killing the USB fifo\r
+                               }\r
+                       else {\r
+                               securityCnt /= 10 ;             // don't wait too long if GetValue failed\r
+                               Sleep(20) ;\r
+                               }\r
+                       }\r
+               if (rval >= 0)\r
+                       break ;\r
+               }\r
+\r
+       return rval ;\r
+       }\r
+\r
+int\r
+CUSBaccess::SetCounter(int deviceNo, int counter, enum COUNTER_IDs counterID) {        //  -1=error, COUNTER_IDs ununsed until now\r
+       const int bufSize = 3 ;\r
+       unsigned char buf[bufSize] ;\r
+       int ok = -1 ;\r
+       int automatic = 0 ;\r
+\r
+       USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+       int version = cwGetVersion(deviceNo) ;\r
+\r
+       if (devType == COUNTER00_DEVICE) {\r
+               buf[0] = CUSBaccess::Configure ;\r
+               buf[1] = counter >> 8 ;\r
+               buf[2] = counter & 0xff ;\r
+               if (SetValue(deviceNo, buf, bufSize))\r
+                       ok = 0 ;\r
+               }\r
+\r
+       return ok ;\r
+       }\r
+\r
+\r
+int            // returns how often switch is manually turned on, -1 in case of an error\r
+CUSBaccess::GetManualOnCount(int deviceNo) {\r
+       const int bufSize = 6 ;\r
+       unsigned char buf[bufSize] ;\r
+       int rval = -1 ;\r
+       USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+       static int sequenceNumber = 1 ;\r
+\r
+       if (    (       devType == SWITCH1_DEVICE \r
+                        || devType == AUTORESET_DEVICE \r
+                        || devType == WATCHDOG_DEVICE)\r
+                       && cwGetVersion(deviceNo) >= 10) {\r
+               for (int timeout=5 ; timeout > 0 ; timeout--) {\r
+                       buf[0] = GetInfo ;\r
+                       buf[1] = ManualCount ;\r
+                       buf[2] = sequenceNumber ;\r
+                       SetValue(deviceNo, buf, 3) ;\r
+                       for (int timeout2=3 ; timeout2 > 0 ; timeout2--) {\r
+                               Sleep(50) ;\r
+                               if (GetValue(deviceNo, buf, bufSize)) {\r
+                                       if ((buf[0] & 0x80) == 0)       // valid bit\r
+                                               continue ;\r
+                                       if (buf[1] != ( (sequenceNumber & 0x1f) << 3 ) + ManualCount)\r
+                                               continue ;\r
+                                       if ((buf[5] & 0x80) == 0)       // valid data bit\r
+                                               continue ;\r
+                                       rval = buf[2] + (buf[3] << 8) + (buf[4] << 16) + ((buf[5] & 0x7f) << 24) ;\r
+                                       break ;\r
+                                       }\r
+                               }\r
+                       if (rval != -1)\r
+                               break ;\r
+                       Sleep(250) ;\r
+                       }\r
+               }\r
+\r
+       sequenceNumber = (++sequenceNumber) & 0x1f ;\r
+\r
+       return rval ;\r
+       }\r
+\r
+int            // returns how long (seconds) switch is manually turned on, -1 in case of an error\r
+CUSBaccess::GetManualOnTime(int deviceNo) {\r
+       const int bufSize = 6 ;\r
+       unsigned char buf[bufSize] ;\r
+       int rval = -1 ;\r
+       USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+       static int sequenceNumber = 1 ;\r
+\r
+       if (    (       devType == SWITCH1_DEVICE \r
+                        || devType == AUTORESET_DEVICE \r
+                        || devType == WATCHDOG_DEVICE)\r
+                       && cwGetVersion(deviceNo) >= 10) {\r
+               for (int timeout=5 ; timeout > 0 ; timeout--) {\r
+                       buf[0] = GetInfo ;\r
+                       buf[1] = ManualTime ;\r
+                       buf[2] = sequenceNumber ;\r
+                       SetValue(deviceNo, buf, 3) ;\r
+                       for (int timeout2=3 ; timeout2 > 0 ; timeout2--) {\r
+                               Sleep(50) ;\r
+                               if (GetValue(deviceNo, buf, bufSize)) {\r
+                                       if ((buf[0] & 0x80) == 0)       // valid bit\r
+                                               continue ;\r
+                                       if (buf[1] != ( (sequenceNumber & 0x1f) << 3 ) + ManualTime)\r
+                                               continue ;\r
+                                       if ((buf[5] & 0x80) == 0)       // valid data bit\r
+                                               continue ;\r
+                                       rval = buf[2] + (buf[3] << 8) + (buf[4] << 16) + ((buf[5] & 0x7f) << 24) ;\r
+                                       break ;\r
+                                       }\r
+                               }\r
+                       if (rval != -1)\r
+                               break ;\r
+                       Sleep(250) ;\r
+                       }\r
+               }\r
+\r
+       if (rval >= 0) {        // rval is 256 * 1,024 ms\r
+               double u_seconds = 256. * 1024. ;\r
+               u_seconds *= rval ;\r
+               rval = (int) (u_seconds / 1000000) ;\r
+               }\r
+\r
+       sequenceNumber = (++sequenceNumber) & 0x1f ;\r
+\r
+       return rval ;\r
+       }\r
+\r
+int            // returns how often switch is turned on by USB command, -1 in case of an error\r
+CUSBaccess::GetOnlineOnCount(int deviceNo) {\r
+       const int bufSize = 6 ;\r
+       unsigned char buf[bufSize] ;\r
+       int rval = -1 ;\r
+       USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+       static int sequenceNumber = 1 ;\r
+       int timeout=-1, timeout2=-1 ;\r
+\r
+       cwDebugWrite("GetOnlineCount\n") ;\r
+\r
+       if (    (       devType == SWITCH1_DEVICE \r
+                        || devType == AUTORESET_DEVICE \r
+                        || devType == WATCHDOGXP_DEVICE \r
+                        || devType == WATCHDOG_DEVICE)\r
+                       && cwGetVersion(deviceNo) >= 10) {\r
+               for (timeout=5 ; timeout > 0 ; timeout--) {\r
+                       buf[0] = GetInfo ;\r
+                       if (devType == WATCHDOGXP_DEVICE) {\r
+                               buf[1] = sequenceNumber ;\r
+                               SetValue(deviceNo, buf, 5) ;\r
+                               }\r
+                       else {\r
+                               buf[1] = OnlineCount ;\r
+                               buf[2] = sequenceNumber ;\r
+                               SetValue(deviceNo, buf, 3) ;\r
+                               }\r
+                       for (timeout2=3 ; timeout2 > 0 ; timeout2--) {\r
+                               Sleep(50) ;\r
+                               if (GetValue(deviceNo, buf, bufSize)) {\r
+                                       if ((buf[0] & 0x80) == 0)       // valid bit\r
+                                               continue ;\r
+                                       if (devType == WATCHDOGXP_DEVICE) {\r
+                                               if (buf[1] != sequenceNumber)\r
+                                                       continue ;\r
+                                               }\r
+                                       else {\r
+                                               if (buf[1] != ( (sequenceNumber & 0x1f) << 3 ) + OnlineCount)\r
+                                                       continue ;\r
+                                               }\r
+                                       if ((buf[5] & 0x80) == 0)       // valid data bit\r
+                                               continue ;\r
+                                       rval = buf[2] + (buf[3] << 8) + (buf[4] << 16) + ((buf[5] & 0x7f) << 24) ;\r
+                                       break ;\r
+                                       }\r
+                               }\r
+                       if (rval != -1)\r
+                               break ;\r
+                       Sleep(250) ;\r
+                       }\r
+               }\r
+\r
+       static char ds[256] ;\r
+       sprintf(ds, "GetOnlineOnCount(%d) %s, seq=%d, time1=%d, time2=%d\n", \r
+                               deviceNo, (rval==-1)?"failed":"ok", sequenceNumber, timeout, timeout2) ;\r
+       cwDebugWrite(ds) ;\r
+\r
+       sequenceNumber = (++sequenceNumber) & 0x1f ;\r
+\r
+       cwDebugWrite("GetOnlineCout\n") ;\r
+\r
+       return rval ;\r
+       }\r
+\r
+int            // returns how long (seconds) switch is turned on by USB command, -1 in case of an error\r
+CUSBaccess::GetOnlineOnTime(int deviceNo) {\r
+       const int bufSize = 6 ;\r
+       unsigned char buf[bufSize] ;\r
+       int rval = -1 ;\r
+       USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+       static int sequenceNumber = 1 ;\r
+\r
+       if (    (       devType == SWITCH1_DEVICE \r
+                        || devType == AUTORESET_DEVICE \r
+                        || devType == WATCHDOG_DEVICE)\r
+                       && cwGetVersion(deviceNo) >= 10) {\r
+               for (int timeout=5 ; timeout > 0 ; timeout--) {\r
+                       buf[0] = GetInfo ;\r
+                       buf[1] = OnlineTime ;\r
+                       buf[2] = sequenceNumber ;\r
+                       SetValue(deviceNo, buf, 3) ;\r
+                       for (int timeout2=3 ; timeout2 > 0 ; timeout2--) {\r
+                               Sleep(50) ;\r
+                               if (GetValue(deviceNo, buf, bufSize)) {\r
+                                       if ((buf[0] & 0x80) == 0)       // valid bit\r
+                                               continue ;\r
+                                       if (buf[1] != ( (sequenceNumber & 0x1f) << 3 ) + OnlineTime)\r
+                                               continue ;\r
+                                       if ((buf[5] & 0x80) == 0)       // valid data bit\r
+                                               continue ;\r
+                                       rval = buf[2] + (buf[3] << 8) + (buf[4] << 16) + ((buf[5] & 0x7f) << 24) ;\r
+                                       break ;\r
+                                       }\r
+                               }\r
+                       if (rval != -1)\r
+                               break ;\r
+                       Sleep(250) ;\r
+                       }\r
+               }\r
+\r
+       if (rval >= 0) {        // rval is 256 * 1,024 ms\r
+               double u_seconds = 256. * 1024. ;\r
+               u_seconds *= rval ;\r
+               rval = (int) (u_seconds / 1000000) ;\r
+               }\r
+\r
+       sequenceNumber = (++sequenceNumber) & 0x1f ;\r
+\r
+       return rval ;\r
+       }\r
+\r
+int \r
+CUSBaccess::ResetDevice(int deviceNo) {\r
+       int ok = 1 ;\r
+       const int bufsize = 6 ;\r
+       unsigned char buf[bufsize] ;\r
+       int version = cwGetVersion(deviceNo) ;\r
+\r
+       buf[0] = CUSBaccess::Reset ;\r
+       buf[1] = 0 ;\r
+       buf[2] = 0 ;\r
+       buf[3] = 0 ;\r
+       buf[4] = 0 ;\r
+       buf[5] = 0 ;\r
+       int type = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+       if (type == TEMPERATURE2_DEVICE || type == HUMIDITY1_DEVICE)\r
+               ok = SetValue(deviceNo, buf, 4) ;\r
+       else if ((type == CONTACT00_DEVICE && version > 6) || type == SWITCHX_DEVICE || type == WATCHDOGXP_DEVICE || type == KEYC01_DEVICE || type == KEYC16_DEVICE)\r
+               ok = SetValue(deviceNo, buf, bufsize) ;\r
+       else if (type == ENCODER01_DEVICE)\r
+               ok = SetValue(deviceNo, buf, bufsize) ;\r
+       else\r
+               ok = SetValue(deviceNo, buf, 3) ;\r
+\r
+       return ok ;\r
+       }\r
+\r
+int \r
+CUSBaccess::StartDevice(int deviceNo) {                // mask in case of CONTACT00-device\r
+       int ok = 1 ;\r
+       const int bufsize = 5 ;\r
+       unsigned char buf[bufsize] ;\r
+       static int sequenceNumber = 1 ;\r
+\r
+/* orginal\r
+       sequenceNumber = (++sequenceNumber) & 0xff ;\r
+       if (sequenceNumber == 0)\r
+               sequenceNumber = 1 ;\r
+*/\r
+       if (++sequenceNumber > 0x7f)    // LINUX sign bit problem\r
+               sequenceNumber = 1 ;\r
+\r
+       buf[0] = CUSBaccess::StartMeasuring ;\r
+       buf[1] = sequenceNumber ;\r
+       buf[2] = 0 ;\r
+       buf[3] = 0 ;\r
+       buf[4] = 0 ;\r
+\r
+       int type = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+       int version = cwGetVersion(deviceNo) ;\r
+\r
+       if (type == TEMPERATURE2_DEVICE || type == HUMIDITY1_DEVICE)\r
+               ok = SetValue(deviceNo, buf, 4) ;\r
+       else if ((type == CONTACT00_DEVICE && version > 6) || type == SWITCHX_DEVICE || type == WATCHDOGXP_DEVICE || type == KEYC01_DEVICE || type == KEYC16_DEVICE)\r
+               ok = SetValue(deviceNo, buf, 5) ;\r
+       else\r
+               ok = SetValue(deviceNo, buf, 3) ;\r
+\r
+       return (ok ? sequenceNumber : 0) ;\r
+       }\r
+\r
+int \r
+CUSBaccess::SyncDevice(int deviceNo, unsigned long int mask) {         // mask in case of CONTACT00-device\r
+       int ok = 1 ;\r
+       const int bufsize = 5 ;\r
+       unsigned char buf[bufsize] ;\r
+       static int sequenceNumber = 1 ;\r
+\r
+/* orginal\r
+       sequenceNumber = (++sequenceNumber) & 0xff ;\r
+       if (sequenceNumber == 0)\r
+               sequenceNumber = 1 ;\r
+*/\r
+       if (++sequenceNumber > 0x7f)    // LINUX signed byte\r
+               sequenceNumber = 1 ;\r
+\r
+       if (mask == 0)\r
+               mask = 0xffff ;         // get every single bit!!\r
+\r
+/* orginal\r
+       buf[0] = CUSBaccess::StartMeasuring ;\r
+       buf[1] = sequenceNumber ;\r
+       buf[2] = 0 ;\r
+       buf[3] = (unsigned char)(mask >> 8) ;\r
+       buf[4] = (unsigned char)(mask & 0xff) ;\r
+*/\r
+// LINUX sign bit problem\r
+       buf[0] = CUSBaccess::StartMeasuring << 4 ;\r
+       if (mask & 0x8000)\r
+               buf[0] |= 0x02 ;\r
+       if (mask & 0x80)\r
+               buf[0] |= 0x01 ;\r
+       // buf[0] = CUSBaccess::StartMeasuring ;\r
+       buf[1] = sequenceNumber ;\r
+       buf[2] = 0 ;\r
+       buf[3] = (unsigned char)(mask >> 8) & 0x7f ;\r
+       buf[4] = (unsigned char)(mask & 0xff) & 0x7f ;\r
+\r
+       int type = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+       int version = cwGetVersion(deviceNo) ;\r
+\r
+       if ((type == CONTACT00_DEVICE&& version > 6) || type == SWITCHX_DEVICE || type == WATCHDOGXP_DEVICE || type == KEYC01_DEVICE || type == KEYC16_DEVICE)\r
+               ok = SetValue(deviceNo, buf, 5) ;\r
+\r
+       return (ok ? sequenceNumber : 0) ;\r
+       }\r
+\r
+int \r
+CUSBaccess::CalmWatchdog(int deviceNo, int minutes, int minutes2restart) {\r
+       int ok = 0 ;\r
+       const int bufsize = 5 ;\r
+       unsigned char buf[bufsize] ;\r
+       USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;\r
+\r
+       buf[0] = CUSBaccess::KeepCalm ;\r
+       buf[1] = minutes ;\r
+       buf[2] = minutes2restart ;\r
+       if (devType == AUTORESET_DEVICE || devType == WATCHDOG_DEVICE || devType == SWITCH1_DEVICE)\r
+               ok = SetValue(deviceNo, buf, 3) ;\r
+       else if (devType == CONTACT00_DEVICE || devType == SWITCHX_DEVICE || devType == WATCHDOGXP_DEVICE)\r
+               ok = SetValue(deviceNo, buf, bufsize) ;\r
+\r
+       return ok ;\r
+       }\r
+\r
+int \r
+CUSBaccess::GetTemperature(int deviceNo, double *Temperature, int *timeID) {\r
+       int ok = 1 ;\r
+       const int maxDevs = 128 ;\r
+       static double lastTemperature[maxDevs] ;\r
+       static int initialized = 0 ;\r
+\r
+       if (!initialized) {\r
+               for (int i=0 ; i < maxDevs ; i++)\r
+                       lastTemperature[i] = -200. ;\r
+               initialized = 1 ;\r
+               }\r
+\r
+       switch ((USBtype_enum)cwGetUSBType(deviceNo)) {\r
+               case TEMPERATURE_DEVICE: {\r
+                       const int bufSize = 6 ;\r
+                       unsigned char buf[bufSize] ;\r
+                       // read temperature \r
+                       if (GetValue(deviceNo, buf, bufSize) == 0) {\r
+                               ok = 0 ;\r
+                               break ;\r
+                               }\r
+                       *timeID  = ((buf[0] & 0x7f) << 8) + buf[1] ;\r
+                       int value = (buf[2] << 5) + (buf[3] >> 3) ;\r
+                       if (value & 0x1000)             // negativ!\r
+                               value = (value & 0xfff) - 0x1000 ;\r
+                       int valid = (buf[0] & 0x80) ;   // MSB = valid-bit\r
+                       if (!valid) { // invalid time\r
+                               ok = 0 ;\r
+                               break ;\r
+                               }\r
+                       *Temperature = value * 0.0625 ;\r
+                       break ;\r
+                       }\r
+               case TEMPERATURE2_DEVICE: {\r
+                       const int bufSize = 7 ;\r
+                       unsigned char buf[bufSize] ;\r
+                       // read temperature \r
+                       if (GetValue(deviceNo, buf, bufSize) == 0) {\r
+                               ok = 0 ;\r
+                               break ;\r
+                               }\r
+                       *timeID  = ((buf[0] & 0x7f) << 8) + buf[1] ;\r
+                       int value = (buf[2] << 5) + (buf[3] >> 3) ;\r
+                       if (value & 0x1000)             // negativ!\r
+                               value = (value & 0xfff) - 0x1000 ;\r
+                       int valid = (buf[0] & 0x80) ;   // MSB = valid-bit\r
+                       if (!valid) { // invalid time\r
+                               ok = 0 ;\r
+                               break ;\r
+                               }\r
+                       *Temperature = value * 0.0625 ;\r
+                       if (*Temperature <= -39.99 || *Temperature > 200.)\r
+                               ok = 0 ;                                        // can't happen!\r
+                       break ;\r
+                       }\r
+               case HUMIDITY1_DEVICE:\r
+               case TEMPERATURE5_DEVICE: {\r
+                       const int bufSize = 7 ;\r
+                       unsigned char buf[bufSize] ;\r
+                       // read temperature \r
+                       if (GetValue(deviceNo, buf, bufSize) == 0) {\r
+                               ok = 0 ;\r
+                               break ;\r
+                               }\r
+\r
+                       int version = cwGetVersion(deviceNo) ;\r
+\r
+                       *timeID  = ((buf[0] & 0x3f) << 8) + buf[1] ;\r
+                       int humi = (buf[2] << 8) + buf[3] ;\r
+                       int temp = (buf[4] << 8) + buf[5] ;\r
+                       int valid = ((buf[0] & 0xc0) == 0xc0) ; // MSB = valid-bit\r
+                       if (valid)\r
+                               valid = ((buf[4] & 0x80) == 0) ;        // MSB must be 0\r
+                       if (valid)\r
+                               valid = (buf[4] != 0) ;                         // if value is > 0x100 (temp=-37,5C) there must be an error\r
+                       if (!valid) { // invalid time\r
+                               ok = 0 ;\r
+                               break ;\r
+                               }\r
+               //      double humidity = -4. + 0.0405 * humi - 2.8 * humi * humi / 1000000 ;\r
+                       if (version < 5)                // 14 bit\r
+                               *Temperature = -40. + 0.01 * temp ;\r
+                       else                                    // 12 bit\r
+                               *Temperature = -40. + 0.04 * temp ;\r
+                       if (*Temperature <= -39.99 || *Temperature > 200.)\r
+                               ok = 0 ;                                        // can't happen!\r
+                       break ;\r
+                       }\r
+               default:\r
+                       ok = 0 ;\r
+                       break ;\r
+               }\r
+\r
+       if (ok && deviceNo < maxDevs) {\r
+               double t = lastTemperature[deviceNo] ;\r
+               if (t > -199.) {\r
+                       if (*Temperature < t - 1. || *Temperature > t + 1.)     // this should be measured twice\r
+#pragma message("das reicht nicht - Fehler tritt auch mit kleinen Differenzen auf (humi 21,4 = 0x5ff, vorher ca.0x615")\r
+                               ok = 0 ;\r
+                       }\r
+               lastTemperature[deviceNo] = *Temperature ;\r
+               }\r
+\r
+       return ok ;\r
+       }\r
+\r
+int \r
+CUSBaccess::GetHumidity(int deviceNo, double *Humidity, int *timeID) {\r
+       int ok = 1 ;\r
+\r
+       switch (cwGetUSBType(deviceNo)) {\r
+               case HUMIDITY1_DEVICE: {\r
+                       const int bufSize = 7 ;\r
+                       unsigned char buf[bufSize] ;\r
+                       // read temperature \r
+                       if (GetValue(deviceNo, buf, bufSize) == 0) {\r
+                               ok = 0 ;\r
+                               break ;\r
+                               }\r
+\r
+                       int version = cwGetVersion(deviceNo) ;\r
+\r
+                       *timeID  = ((buf[0] & 0x3f) << 8) + buf[1] ;\r
+                       int humi = (buf[2] << 8) + buf[3] ;\r
+                       int valid = ((buf[0] & 0xc0) == 0xc0) ; // MSB = valid-bit\r
+                       if (valid)\r
+                               valid = ((buf[2] & 0x80) == 0) ;        // MSB must be 0\r
+                       if (!valid) { // invalid time\r
+                               ok = 0 ;\r
+                               break ;\r
+                               }\r
+               //      *Temperature = -40. + 0.01 * temp ;\r
+                       if (version < 5)                // 12 bit\r
+                               *Humidity = -4. + 0.0405 * humi - 2.8 * humi * humi / 1000000 ;\r
+                       else                                    //  8 bit\r
+                               *Humidity = -4. + 0.648 * humi - 7.2 * humi * humi / 10000 ;\r
+                       if (*Humidity < 0.)\r
+                               ok = 0 ;                                // this is not possible!!\r
+                       break ;\r
+                       }\r
+               default:\r
+                       ok = 0 ;\r
+                       break ;\r
+               }\r
+       return ok ;\r
+       }\r
+       \r
+\r
+int            // return 0 for pre 2014 designed devices, 13 for new devices\r
+CUSBaccess::GetHWversion(int deviceNo) {\r
+       int rval = cwGetHWversion(deviceNo) ;\r
+\r
+       return rval ;\r
+       }\r
+\r
+// returns data if ok or -1 in case of an error\r
+int            \r
+CUSBaccess::IOX(int deviceNo, int addr, int data) {\r
+       int rval = cwIOX(deviceNo, addr, data) ;\r
+\r
+       return rval ;\r
+       }\r
+\r
+\r
+void\r
+CUSBaccess::DebugWrite(char *s) { \r
+       cwDebugWrite(s) ;\r
+       }\r
+\r
+void\r
+CUSBaccess::DebugWrite(char *f, int a1) {\r
+       static char s[1024] ;\r
+       sprintf(s, f, a1) ;\r
+       cwDebugWrite(s) ;\r
+       }\r
+\r
+void\r
+CUSBaccess::DebugWrite(char *f, int a1,int a2) { \r
+       static char s[1024] ;\r
+       sprintf(s, f, a1, a2) ;\r
+       cwDebugWrite(s) ;\r
+       }\r
+\r
+void\r
+CUSBaccess::DebugWrite(char *f, int a1, int a2, int a3) { \r
+       static char s[1024] ;\r
+       sprintf(s, f, a1, a2, a3) ;\r
+       cwDebugWrite(s) ;\r
+       }\r
+\r
+void\r
+CUSBaccess::DebugWrite(char *f, int a1, int a2, int a3, int a4) { \r
+       static char s[1024] ;\r
+       sprintf(s, f, a1, a2, a3, a4) ;\r
+       cwDebugWrite(s) ;\r
+       }\r
diff --git a/USBaccess.h b/USBaccess.h
new file mode 100644 (file)
index 0000000..7fd51a1
--- /dev/null
@@ -0,0 +1,131 @@
+// DLL class definitions for access to USB HID devices\r
+//\r
+// (C) 2001-2014 Copyright Cleware GmbH\r
+// All rights reserved\r
+//\r
+// History:\r
+// 05.01.2001  ws      Initial coding\r
+// 17.07.2001  ws      cleanup interface\r
+// 10.12.2001  ws      cleanup interface again, basic class to hide implementation details\r
+// 13.12.2001  ws      introduced versionNumber and virtual destructor\r
+// 23.05.2002  ws      added switch access\r
+// ...\r
+// 03.02.2003  ws      added switch version 10 \r
+// 04.08.2003  ws      added humidity \r
+// 21.01.2004  ws      fixed some humidity problems \r
+//                2004 ws      added contact + io16\r
+// 05.02.2005  ws      added ADC08-Support \r
+// 25.05.13   ws       new controller support\r
+// 15.05.2014  ws      4.3.0   added new controller support\r
+\r
+\r
+\r
+// The following ifdef block is the standard way of creating macros which make exporting \r
+// from a DLL simpler. All files within this DLL are compiled with the USBACCESS_EXPORTS\r
+// symbol defined on the command line. this symbol should not be defined on any project\r
+// that uses this DLL. This way any other project whose source files include this file see \r
+// USBACCESS_API functions as being imported from a DLL, wheras this DLL sees symbols\r
+// defined with this macro as being exported.\r
+\r
+\r
+#ifndef __USBACCESS_H__\r
+#define __USBACCESS_H__\r
+\r
+#ifdef __APPLE__\r
+#include "mac-hidapi/hidapi.h"\r
+#else\r
+#include <hidapi/hidapi.h>\r
+#endif\r
+\r
+typedef hid_device * HANDLE;\r
+\r
+const int USBaccessVersion = 330 ;\r
+\r
+class CUSBaccess {\r
+       public:\r
+               enum USBactions {               LEDs=0, EEwrite=1, EEread=2, Reset=3, KeepCalm=4, GetInfo=5, \r
+                                                               StartMeasuring=6,               // USB-Humidity\r
+                                                               Configure=7,                    // USB-IO16-V10, USB-Counter-V05\r
+                                                               RunPoint=10                             // USB-Encoder\r
+                                                               } ;\r
+               enum USBInfoType {              OnlineTime=1, OnlineCount=2, ManualTime=3, ManualCount=4 } ;\r
+               enum LED_IDs {                  LED_0=0, LED_1=1, LED_2=2, LED_3=3 } ;\r
+               enum COUNTER_IDs {              COUNTER_0=0, COUNTER_1=1 } ;\r
+               enum SWITCH_IDs {               SWITCH_0=0x10, SWITCH_1=0x11, SWITCH_2=0x12, SWITCH_3=0x13,\r
+                                                               SWITCH_4=0x14, SWITCH_5=0x15, SWITCH_6=0x16, SWITCH_7=0x17,\r
+                                                               SWITCH_8=0x18, SWITCH_9=0x19, SWITCH_10=0x1a, SWITCH_11=0x1b,\r
+                                                               SWITCH_12=0x1c, SWITCH_13=0x1d, SWITCH_14=0x1e, SWITCH_15=0x1f\r
+                                                               } ;\r
+               enum USBtype_enum {             ILLEGAL_DEVICE=0,\r
+                                                               LED_DEVICE=0x01,\r
+                                                               POWER_DEVICE=0x02,\r
+                                                               WATCHDOG_DEVICE=0x05,\r
+                                                               AUTORESET_DEVICE=0x06,\r
+                                                               WATCHDOGXP_DEVICE=0x07,\r
+                                                               SWITCH1_DEVICE=0x08,\r
+                                                               SWITCH2_DEVICE=0x09, SWITCH3_DEVICE=0x0a, SWITCH4_DEVICE=0x0b,\r
+                                                               SWITCH5_DEVICE=0x0c, SWITCH6_DEVICE=0x0d, SWITCH7_DEVICE=0x0e, SWITCH8_DEVICE=0x0f,\r
+                                                               TEMPERATURE_DEVICE=0x10, \r
+                                                               TEMPERATURE2_DEVICE=0x11,\r
+                                                               TEMPERATURE5_DEVICE=0x15, \r
+                                                               HUMIDITY1_DEVICE=0x20,\r
+                                                               SWITCHX_DEVICE=0x28,            // new switch 3,4,8\r
+                                                               CONTACT00_DEVICE=0x30, CONTACT01_DEVICE=0x31, CONTACT02_DEVICE=0x32, CONTACT03_DEVICE=0x33, \r
+                                                               CONTACT04_DEVICE=0x34, CONTACT05_DEVICE=0x35, CONTACT06_DEVICE=0x36, CONTACT07_DEVICE=0x37, \r
+                                                               CONTACT08_DEVICE=0x38, CONTACT09_DEVICE=0x39, CONTACT10_DEVICE=0x3a, CONTACT11_DEVICE=0x3b, \r
+                                                               CONTACT12_DEVICE=0x3c, CONTACT13_DEVICE=0x3d, CONTACT14_DEVICE=0x3e, CONTACT15_DEVICE=0x3f, \r
+                                                               F4_DEVICE=0x40, \r
+                                                               KEYC01_DEVICE=0x41, KEYC16_DEVICE=0x42,\r
+                                                               ADC0800_DEVICE=0x50, ADC0801_DEVICE=0x51, ADC0802_DEVICE=0x52, ADC0803_DEVICE=0x53, \r
+                                                               COUNTER00_DEVICE=0x60, \r
+                                                               ENCODER01_DEVICE=0x80,\r
+                                                               BUTTON_NODEVICE=0x1000\r
+                                                               } ;\r
+       private:\r
+               class CUSBaccessBasic * X       ;       // avoid export of internal USB variables\r
+\r
+       public:\r
+               CUSBaccess() ;\r
+               virtual ~CUSBaccess() ;         // maybe used as base class\r
+\r
+               virtual int                     OpenCleware() ;                 // returns number of found Cleware devices\r
+               virtual int                     CloseCleware() ;                // close all Cleware devices\r
+               virtual int                     Recover(int devNum) ;   // try to find disconnected devices, returns true if succeeded\r
+               virtual HANDLE          GetHandle(int deviceNo) ;\r
+               virtual int                     GetValue(int deviceNo, unsigned char *buf, int bufsize) ;\r
+               virtual int                     SetValue(int deviceNo, unsigned char *buf, int bufsize) ;\r
+               virtual int                     SetLED(int deviceNo, enum LED_IDs Led, int value) ;     // value: 0=off 7=medium 15=highlight\r
+               virtual int                     SetSwitch(int deviceNo, enum SWITCH_IDs Switch, int On) ;       //      On: 0=off, 1=on\r
+               virtual int                     GetSwitch(int deviceNo, enum SWITCH_IDs Switch) ;                       //      On: 0=off, 1=on, -1=error\r
+               virtual int                     GetSeqSwitch(int deviceNo, enum SWITCH_IDs Switch, int seqNum) ;                //      On: 0=off, 1=on, -1=error\r
+               virtual int                     GetSwitchConfig(int deviceNo, int *switchCount, int *buttonAvailable) ;\r
+               virtual int                     GetTemperature(int deviceNo, double *Temperature, int *timeID) ;\r
+               virtual int                     GetHumidity(int deviceNo, double *Humidity, int *timeID) ;\r
+               virtual int                     ResetDevice(int deviceNo) ;\r
+               virtual int                     StartDevice(int deviceNo) ;     \r
+               virtual int                     CalmWatchdog(int deviceNo, int minutes, int minutes2restart) ;\r
+               virtual int                     GetVersion(int deviceNo) ;\r
+               virtual int                     GetUSBType(int deviceNo) ;\r
+               virtual int                     GetSerialNumber(int deviceNo) ;\r
+               virtual int                     GetDLLVersion() { return USBaccessVersion ; }\r
+               virtual int                     GetManualOnCount(int deviceNo) ;                // returns how often switch is manually turned on\r
+               virtual int                     GetManualOnTime(int deviceNo) ;                 // returns how long (seconds) switch is manually turned on\r
+               virtual int                     GetOnlineOnCount(int deviceNo) ;                // returns how often switch is turned on by USB command\r
+               virtual int                     GetOnlineOnTime(int deviceNo) ;                 // returns how long (seconds) switch is turned on by USB command\r
+               virtual int                     GetMultiSwitch(int deviceNo, unsigned long int *mask, unsigned long int *value, int seqNumber) ;\r
+               virtual int                     SetMultiSwitch(int deviceNo, unsigned long int value) ;\r
+               virtual int                     SetMultiConfig(int deviceNo, unsigned long int directions) ;\r
+               virtual int                     GetCounter(int deviceNo, enum COUNTER_IDs counterID) ;  // COUNTER_IDs ununsed until now\r
+               virtual int                     SetCounter(int deviceNo, int counter, enum COUNTER_IDs counterID) ;     //  -1=error, COUNTER_IDs ununsed until now\r
+               virtual int                     SyncDevice(int deviceNo, unsigned long int mask) ;\r
+               virtual int                     GetHWversion(int deviceNo) ;    // return HWversion (0 for pre 2014 designed devices, 13 for new devices)\r
+               virtual int                     IOX(int deviceNo, int addr, int data) ;         // for internal use only, wrong usage may destroy device        \r
+               virtual void            DebugWrite(char *s) ;\r
+               virtual void            DebugWrite(char *f, int a1) ;\r
+               virtual void            DebugWrite(char *f, int a1, int a2) ;\r
+               virtual void            DebugWrite(char *f, int a1, int a2, int a3) ;\r
+               virtual void            DebugWrite(char *f, int a1, int a2, int a3, int a4) ;\r
+               virtual void            Sleep(int ms) { usleep(ms * 1000) ; }   // for Linux\r
+       } ;\r
+\r
+#endif // __USBACCESS_H__\r
diff --git a/USBaccessBasic.cpp b/USBaccessBasic.cpp
new file mode 100644 (file)
index 0000000..2785009
--- /dev/null
@@ -0,0 +1,521 @@
+// Basic class implementation for access to USB HID devices\r
+//\r
+// (C) 2001 Copyright Cleware GmbH\r
+// All rights reserved\r
+//\r
+// Converted to HidApi by folkert van Heusden, mail@vanheusden.com\r
+//\r
+// History:\r
+// 05.01.01    ws      Initial coding\r
+// 01.11.01    ws      Linux coding\r
+// 30.10.12    fvh     libusb version\r
+\r
+#include <errno.h>\r
+#include <stdlib.h>\r
+#include <unistd.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include <fcntl.h>\r
+\r
+#include "USBaccessBasic.h"\r
+\r
+#define TIMEOUT 1000\r
+\r
+const int maxHID = 256 ;\r
+SUSBdata data[256] ;\r
+\r
+int nr = 0;\r
+\r
+void cwInitCleware()\r
+{\r
+       hid_init();\r
+}\r
+\r
+void cwCloseCleware()\r
+{\r
+       for(int h=0; h < maxHID; h++)\r
+       {\r
+               if (data[h].handle)\r
+               {\r
+                       hid_close(data[h].handle);\r
+\r
+                       data[h].handle = NULL;\r
+               }\r
+       }\r
+\r
+       hid_exit();\r
+}\r
+\r
+int    \r
+cwIOX(int deviceNo, int addr, int datum) {     // return datum if ok, datum=-1=Read operation\r
+       const int maxbufsize = 8 ;\r
+       int bufsize = 6 ;\r
+       unsigned char buf[maxbufsize] ;\r
+       int ok = 1 ;\r
+       if (deviceNo < 0 || deviceNo >= maxHID || data[deviceNo].handle == NULL)\r
+               return-1 ;\r
+\r
+       int devType = data[deviceNo].gadgettype ;\r
+       int version = data[deviceNo].gadgetVersionNo ;\r
+       int sixteenbit = (devType == TEMPERATURE2_DEVICE || devType == HUMIDITY1_DEVICE || devType == HUMIDITY2_DEVICE) ;\r
+\r
+       if (datum >= 0) {               // -1 = Read command\r
+               buf[0] = EEwrite ;\r
+               if (sixteenbit) {\r
+                       buf[1] = addr >> 8 ;    // high byte 0\r
+                       buf[2] = addr ;\r
+                       buf[3] = datum ;\r
+                       cwSetValue(deviceNo, buf, 4) ;\r
+                       }\r
+               else if (devType == CONTACT00_DEVICE && version > 6) {\r
+                       buf[1] = addr ;\r
+                       buf[2] = datum ;\r
+                       cwSetValue(deviceNo, buf, 5) ;\r
+                       }\r
+               else if (devType == DISPLAY_DEVICE) {\r
+                       buf[1] = addr ;\r
+                       buf[2] = datum ;\r
+                       cwSetValue(deviceNo, buf, 5) ;\r
+                       }\r
+               else if (devType == WATCHDOGXP_DEVICE || devType == SWITCHX_DEVICE) {\r
+                       buf[1] = addr ;\r
+                       buf[2] = datum ;\r
+                       cwSetValue(deviceNo, buf, 5) ;\r
+                       }\r
+               else if (devType == ENCODER01_DEVICE) {\r
+                       buf[1] = addr ;\r
+                       buf[2] = datum ;\r
+                       cwSetValue(deviceNo, buf, 6) ;\r
+                       }\r
+               else if (devType == ADC0800_DEVICE) {\r
+                       buf[1] = addr ;\r
+                       buf[2] = datum ;\r
+                       cwSetValue(deviceNo, buf, 3) ;\r
+                       }\r
+               else if (devType == POWER_DEVICE) {\r
+                       buf[1] = addr ;\r
+                       buf[2] = datum ;\r
+                       cwSetValue(deviceNo, buf, 3) ;\r
+                       }\r
+               else if (devType == KEYC16_DEVICE || devType == KEYC01_DEVICE) {\r
+                       buf[1] = addr ;\r
+                       buf[2] = datum ;\r
+                       cwSetValue(deviceNo, buf, 5) ;\r
+                       }\r
+               else if (devType == MOUSE_DEVICE) {\r
+                       buf[1] = addr ;\r
+                       buf[2] = datum ;\r
+                       cwSetValue(deviceNo, buf, 5) ;\r
+                       }\r
+               else {\r
+                       buf[1] = addr ;\r
+                       buf[2] = datum ;\r
+                       cwSetValue(deviceNo, buf, 3) ;\r
+                       }\r
+               usleep(100*1000) ;\r
+               }\r
+\r
+       buf[0] = EEread ;\r
+       if (sixteenbit) {\r
+               buf[1] = 0 ;    // high byte 0\r
+               buf[2] = addr ;\r
+               buf[3] = 0 ;\r
+               cwSetValue(deviceNo, buf, 4) ;\r
+               bufsize = 7 ;\r
+               }\r
+       else if (devType == CONTACT00_DEVICE && version > 6) {\r
+               buf[1] = addr ;\r
+               buf[2] = 0 ;\r
+               cwSetValue(deviceNo, buf, 5) ;\r
+               }\r
+       else if (devType == DISPLAY_DEVICE) {\r
+               buf[1] = addr ;\r
+               buf[2] = 0 ;\r
+               cwSetValue(deviceNo, buf, 5) ;\r
+               }\r
+       else if (devType == WATCHDOGXP_DEVICE || devType == SWITCHX_DEVICE) {\r
+               buf[1] = addr ;\r
+               buf[2] = 0 ;\r
+               cwSetValue(deviceNo, buf, 5) ;\r
+               }\r
+       else if (devType == KEYC16_DEVICE || devType == KEYC01_DEVICE) {\r
+               buf[1] = addr ;\r
+               buf[2] = 0 ;\r
+               cwSetValue(deviceNo, buf, 5) ;\r
+               bufsize = 8 ;\r
+               }\r
+       else if (devType == MOUSE_DEVICE) {\r
+               buf[1] = addr ;\r
+               buf[2] = 0 ;\r
+               cwSetValue(deviceNo, buf, 5) ;\r
+               bufsize = 4 ;\r
+               }\r
+       else if (devType == ADC0800_DEVICE) {\r
+               buf[1] = addr ;\r
+               buf[2] = 0 ;\r
+               cwSetValue(deviceNo, buf, 3) ;\r
+               bufsize = 4 ;\r
+               }\r
+       else if (devType == POWER_DEVICE) {\r
+               buf[1] = addr ;\r
+               buf[2] = 0 ;\r
+               cwSetValue(deviceNo, buf, 3) ;\r
+               bufsize = 3 ;\r
+               }\r
+       else if (devType == ENCODER01_DEVICE) {\r
+               buf[1] = addr ;\r
+               buf[2] = 0 ;\r
+               cwSetValue(deviceNo, buf, 6) ;\r
+               }\r
+       else {\r
+               buf[1] = addr ;\r
+               buf[2] = 0 ;\r
+               cwSetValue(deviceNo, buf, 3) ;\r
+               }\r
+\r
+       usleep(10*1000) ;\r
+       ok = 40 ;\r
+       int Xdata = -1 ;\r
+       while (ok) {\r
+               if (cwGetValue(deviceNo, buf, bufsize)) {\r
+                       if ((buf[0] & 0x80) == 0) {\r
+                               if (--ok == 0) {\r
+                                       // MessageBox("GetValue still not valid", "Error") ;\r
+                                       break ;\r
+                                       }\r
+                               else {\r
+                                       usleep(10*1000) ;\r
+                                       continue ;\r
+                                       }\r
+                               }\r
+                       int Xaddr = 0 ;\r
+                       if (bufsize == 3 || devType == MOUSE_DEVICE) {\r
+                               Xaddr = buf[1] ;\r
+                               Xdata = buf[2] ;\r
+                               }\r
+                       else if (bufsize == 4) {\r
+                               Xaddr = buf[2] ;\r
+                               Xdata = buf[3] ;\r
+                               }\r
+                       else {\r
+                               Xaddr = buf[4] ;\r
+                               Xdata = buf[5] ;\r
+                               }\r
+                       if (sixteenbit) {\r
+                               Xaddr = (Xaddr << 8) + buf[5] ;\r
+                               Xdata = buf[6] ;\r
+                               }\r
+                       if (Xaddr != addr) {\r
+                               if (--ok == 0) {\r
+                                       // MessageBox("GetValue address error", "Error") ;\r
+                                       break ;\r
+                                       }\r
+                               else {\r
+                                       usleep(10*1000) ;\r
+                                       continue ;\r
+                                       }\r
+                               }\r
+                       if (datum >= 0 && Xdata != datum) {\r
+                               if (--ok == 0) {\r
+                                       // MessageBox("Write error", "Error") ;\r
+                                       break ;\r
+                                       }\r
+                               else {\r
+                                       usleep(10*1000) ;\r
+                                       continue ;\r
+                                       }\r
+                               }\r
+                       break ;\r
+                       }\r
+               else {\r
+                       if (--ok == 0) {\r
+                               // MessageBox("GetValue failed", "Error") ;\r
+                               break ;\r
+                               }\r
+                       else {\r
+                               usleep(10*1000) ;\r
+                               continue ;\r
+                               }\r
+                       }\r
+               break ;         // read was ok\r
+               }\r
+       if (!ok)\r
+               Xdata = -1 ;\r
+\r
+       return Xdata ;\r
+       }\r
+\r
+// returns number of found Cleware devices\r
+int cwOpenCleware(const char *path = NULL)\r
+{\r
+       int n = 0;\r
+       struct hid_device_info *devs = NULL, *cur_dev = NULL;\r
+\r
+       memset(&data, 0x00, sizeof data);\r
+\r
+       cur_dev = devs = hid_enumerate(0x0d50, 0x0);\r
+\r
+       while (cur_dev)\r
+       {\r
+               data[n].v = cur_dev->vendor_id;\r
+               data[n].p = cur_dev->product_id;\r
+               data[n].hidpath = strdup(cur_dev->path);\r
+\r
+               data[n].gadgettype = (enum USBtype_enum)data[n].p;\r
+               data[n].gadgetVersionNo = cur_dev -> release_number;\r
+\r
+                char buffer[256] = { 0 };\r
+                wcstombs(buffer, cur_dev->serial_number, wcslen(cur_dev->serial_number));\r
+\r
+                data[n].SerialNumber = strtol(buffer, NULL, 16);\r
+               data[n].report_type = 123; // HID_REPORT_ID_FIRST; // NOT USED *FVH*\r
+               if (data[n].SerialNumber == 0x63813) {  // this is the next controller - get serial number directly\r
+                       data[n].HWversion = 13 ;\r
+                       data[n].SerialNumber = -1 ;\r
+               }\r
+               if (data[n].SerialNumber <= 0) {                // getting the Serial number failed, so get it directly!\r
+                       data[n].handle = hid_open_path(data[n].hidpath);\r
+                       int SerNum = 0 ;\r
+                       int addr = 0;\r
+                       for (addr=8 ; addr <= 14 ; addr++) {    // unicode byte 2 == 0\r
+                               int data = cwIOX(n, addr, -1) ;\r
+                               if (data >= '0' && data <= '9')\r
+                                       SerNum = SerNum * 16 + data - '0' ;\r
+                               else if (data >= 'A' && data <= 'F')\r
+                                       SerNum = SerNum * 16 + data - 'A' + 10 ;\r
+                               else {\r
+                                       SerNum = -1 ;           // failed!\r
+                                       break ;\r
+                               }\r
+                       }\r
+                       data[n].SerialNumber = SerNum ;\r
+                       hid_close(data[n].handle);\r
+                       data[n].handle = NULL;\r
+               }\r
+\r
+               n++;\r
+               cur_dev = cur_dev->next;\r
+       }\r
+\r
+       hid_free_enumeration(devs);\r
+\r
+       return n;\r
+}\r
+\r
+int cwOpenDevice(int index)\r
+{\r
+       if (data[index].handle)\r
+               return 1;\r
+\r
+       data[index].handle = hid_open_path(data[index].hidpath);\r
+\r
+       char ok = data[index].handle != NULL;\r
+\r
+       if (!ok)\r
+               fprintf(stderr, "Failed to open %04x:%04x (%d)\n", data[index].v, data[index].p, data[index].SerialNumber);\r
+\r
+       return ok;\r
+}\r
+\r
+int cwCloseDevice(int index)\r
+{\r
+       if (data[index].handle)\r
+       {\r
+               hid_close(data[index].handle);\r
+\r
+               data[index].handle = NULL;\r
+       }\r
+\r
+       return 1;\r
+}\r
+\r
+int cwRecover(int devNo)\r
+{\r
+       if (data[devNo].handle == NULL)\r
+               return 0;\r
+\r
+       return 1;\r
+}\r
+\r
+void fail(const char *msg, hid_device *handle)\r
+{\r
+       const wchar_t *wstr = hid_error(handle);\r
+\r
+       if (!wstr)\r
+       {\r
+               if (errno)\r
+                       printf("%s: %s\n", msg, strerror(errno));\r
+               else\r
+                       printf("%s\n", msg);\r
+       }\r
+       else\r
+       {\r
+               int len = wcslen(wstr);\r
+               char* ascii = new char[len + 1];\r
+\r
+               wcstombs(ascii, wstr, len);\r
+\r
+               printf("%s: %s\n", msg, ascii);\r
+\r
+               delete [] ascii;\r
+       }\r
+}\r
+\r
+int cwGetValue(int deviceNo, unsigned char *buf, int bufsize)\r
+{\r
+       if (!cwOpenDevice(deviceNo))\r
+               return 0;\r
+\r
+       if (data[deviceNo].handle == NULL)\r
+               return 0;\r
+\r
+       unsigned char lbuf[3] = { 0x00, (unsigned char)(nr++), 0x81 };\r
+       if (hid_send_feature_report(data[deviceNo].handle, lbuf, sizeof lbuf) < 0)\r
+       {\r
+               fail("cwGetValue::hid_write() failed", data[deviceNo].handle);\r
+\r
+                return 0;\r
+        }\r
+\r
+       if (hid_read(data[deviceNo].handle, buf, bufsize) < 0)\r
+       {\r
+               fail("cwGetValue::hid_read() failed", data[deviceNo].handle);\r
+\r
+                return 0;\r
+        }\r
+\r
+       return 1;\r
+}\r
+\r
+int cwSetValue(int deviceNo, unsigned char *buf, int bufsize)\r
+{\r
+       if (!cwOpenDevice(deviceNo))\r
+               return 0;\r
+\r
+       if (data[deviceNo].handle == NULL)\r
+               return 0;\r
+\r
+       char *b = new char[bufsize + 1];\r
+       memcpy(b + 1, buf, bufsize);\r
+       b[0] = 0x00;\r
+\r
+//#ifdef macos\r
+#if 1\r
+       if (hid_write(data[deviceNo].handle, (unsigned char *)b, bufsize + 1) < 0)\r
+#else\r
+       if (hid_send_feature_report(data[deviceNo].handle, (unsigned char *)b, bufsize + 1) < 0)\r
+#endif\r
+       {\r
+               fail("cwSetValue::hid_write() failed", data[deviceNo].handle);\r
+\r
+               delete [] b;\r
+\r
+                return 0;\r
+        }\r
+\r
+       delete [] b;\r
+\r
+       return 1;\r
+}\r
+\r
+hid_device * cwGetHandle(int deviceNo)\r
+{ \r
+       if (!cwOpenDevice(deviceNo))\r
+               return 0;\r
+\r
+       return data[deviceNo].handle;\r
+}\r
+\r
+int cwGetVersion(int deviceNo)\r
+{\r
+       return data[deviceNo].gadgetVersionNo;\r
+}\r
+\r
+int cwGetSerialNumber(int deviceNo)\r
+{ \r
+       return data[deviceNo].SerialNumber;\r
+}\r
+\r
+enum USBtype_enum cwGetUSBType(int deviceNo)\r
+{ \r
+       return data[deviceNo].gadgettype;\r
+}\r
+\r
+int\r
+cwValidSerNum(int SerialNumber, enum USBtype_enum devType) {\r
+       static int outdated[] = {\r
+               54,59,60,62,63,64,65,66,67,68,69,\r
+               72,74,75,76,77,82,83,85,87,88,89,\r
+               90,91,92,93,95,96,98,99,\r
+               100,101,102,103,105,106,107,108,109,110,\r
+               113,116,117,119,120,122,124,125,126,128,\r
+               131,132,135,139,140,142,143,145,147,148,149,\r
+               150,151,152,153,154,155,156,157,160,161,162,163,168,169,\r
+               170,171,172,173,174,175,176,180,184,187,188,189,190,191,192,193,195,197,198,\r
+               201,203,204, 205, 206, 219,220,221,260,272,273,274,275,276,278,279,\r
+               280,281,416,\r
+               5002,5003,5004,5005,5006,5007,5008,5010,\r
+               5011,5012,5013,5014,5015,5016,\r
+               5017,5018,5019,5020,5021,5022,5023,5024,\r
+               5025,5026,5028,5029,5032,5033,5034,\r
+               5035,5036,5041,5043,5044,5046,5049,5050,\r
+               5052,5053,5055,5057,5071,5073,5076,5089,5091,5101,5102,5103,\r
+               5104,5106,5109,5114,5116,5117,5118,5119,\r
+               5120,5121,5122,5147,5163,5164,7502,7503,\r
+               7504,7505,7511,7513,8192,8193,8194,\r
+               8503,8504,8505,8506,8507,8508,8509,8510,8511,8512,8513\r
+               } ;\r
+\r
+       static int outdatedSwitches[] = {               // double numbers!!\r
+               510,511,513,514,517,518,520,532                 //      Switches\r
+//             , 5314  // test\r
+               } ;\r
+\r
+       int rval = 1 ;\r
+\r
+       int size = sizeof(outdated) / sizeof(int) ;\r
+       int *pt = &(outdated[0]) ;\r
+       int i ;\r
+\r
+       for (i=0 ; i < size ; i++, pt++) {\r
+               if (SerialNumber == *pt) {\r
+                       rval = 0 ;\r
+                       break ;\r
+                       }\r
+               }\r
+       if (rval == 1 && devType == SWITCH1_DEVICE) {\r
+               size = sizeof(outdatedSwitches) / sizeof(int) ;\r
+               pt = &(outdatedSwitches[0]) ;\r
+               for (i=0 ; i < size ; i++, pt++) {\r
+                       if (SerialNumber == *pt) {\r
+                               rval = 0 ;\r
+                               break ;\r
+                               }\r
+                       }\r
+               }\r
+\r
+       return rval ; \r
+       }\r
+\r
+void\r
+cwDebugWrite(char *s) { \r
+       fputs(s, stderr) ;\r
+       }\r
+\r
+void\r
+cwDebugClose() { \r
+       }\r
+\r
+int\r
+cwGetHWversion(int deviceNo) {                  // return current\r
+        int rval = 0 ;\r
+\r
+        if (deviceNo < 0 || deviceNo >= maxHID || data[deviceNo].handle == NULL)\r
+                rval = -1 ;\r
+        else\r
+                rval = data[deviceNo].HWversion ;\r
+\r
+        return rval ;\r
+        }\r
diff --git a/USBaccessBasic.h b/USBaccessBasic.h
new file mode 100644 (file)
index 0000000..629995c
--- /dev/null
@@ -0,0 +1,87 @@
+// Basic class definitions for access to USB HID devices\r
+//\r
+// (C) 2001 Copyright Cleware GmbH\r
+// All rights reserved\r
+//\r
+// History:\r
+// 05.01.01    ws      Initial coding\r
+// 17.07.01    ws      cleanup interface\r
+// 03.11.02    ws      small changes for Linux\r
+\r
+\r
+#ifndef __USBACCESSBASIC_H__\r
+#define __USBACCESSBASIC_H__\r
+\r
+#ifdef __APPLE__\r
+#include "mac-hidapi/hidapi.h"\r
+#else\r
+#include <hidapi/hidapi.h>\r
+#endif\r
+\r
+typedef hid_device * HANDLE;\r
+\r
+enum USBtype_enum {    ILLEGAL_DEVICE=0,\r
+                                               LED_DEVICE=0x01,\r
+                                               POWER_DEVICE=0x02,\r
+                                               DISPLAY_DEVICE=0x03,\r
+                                               WATCHDOG_DEVICE=0x05,\r
+                                               AUTORESET_DEVICE=0x06,\r
+                                               WATCHDOGXP_DEVICE=0x07,\r
+                                               SWITCH1_DEVICE=0x08,\r
+                                               SWITCH2_DEVICE=0x09, SWITCH3_DEVICE=0x0a, SWITCH4_DEVICE=0x0b,\r
+                                               SWITCH5_DEVICE=0x0c, SWITCH6_DEVICE=0x0d, SWITCH7_DEVICE=0x0e, SWITCH8_DEVICE=0x0f,\r
+                                               TEMPERATURE_DEVICE=0x10,\r
+                                               TEMPERATURE2_DEVICE=0x11,\r
+                                               TEMPERATURE5_DEVICE=0x15, \r
+                                               HUMIDITY1_DEVICE=0x20,HUMIDITY2_DEVICE=0x21,\r
+                                               SWITCHX_DEVICE=0x28,            // new switch 3,4,8\r
+                                               // CONTACT1_DEVICE=0x30 \r
+                                               CONTACT00_DEVICE=0x30, CONTACT01_DEVICE=0x31, CONTACT02_DEVICE=0x32, CONTACT03_DEVICE=0x33, \r
+                                               CONTACT04_DEVICE=0x34, CONTACT05_DEVICE=0x35, CONTACT06_DEVICE=0x36, CONTACT07_DEVICE=0x37, \r
+                                               CONTACT08_DEVICE=0x38, CONTACT09_DEVICE=0x39, CONTACT10_DEVICE=0x3a, CONTACT11_DEVICE=0x3b, \r
+                                               CONTACT12_DEVICE=0x3c, CONTACT13_DEVICE=0x3d, CONTACT14_DEVICE=0x3e, CONTACT15_DEVICE=0x3f, \r
+                                               F4_DEVICE=0x40, \r
+                                               KEYC01_DEVICE=0x41, KEYC16_DEVICE=0x42,MOUSE_DEVICE=0x43,\r
+                                               ADC0800_DEVICE=0x50, ADC0801_DEVICE=0x51, ADC0802_DEVICE=0x52, ADC0803_DEVICE=0x53, \r
+                                               COUNTER00_DEVICE=0x60, \r
+                                               ENCODER01_DEVICE=0x80,\r
+                                               BUTTON_NODEVICE=0x1000\r
+                                               } ;\r
+enum USBactions {              LEDs=0, EEwrite=1, EEread=2, Reset=3, KeepCalm=4, GetInfo=5, \r
+                                               StartMeasuring=6,               // USB-Humidity\r
+                                               Configure=7,                    // USB-IO16-V10, USB-Counter-V05\r
+                                               Display=8,                              // USB/Display\r
+                                               RunPoint=10,                    // USB-Encoder\r
+                                               Programm=15                             // Transfer new Firmware (internal use only)\r
+                                               } ;\r
+\r
+typedef struct {\r
+       unsigned short v, p;\r
+       hid_device *handle;\r
+       int     gadgetVersionNo;\r
+       enum USBtype_enum       gadgettype;\r
+       int     SerialNumber;\r
+       int     report_type;\r
+       int     HWversion ;\r
+       char    *hidpath;\r
+       } SUSBdata;\r
+\r
+extern int nr;\r
+\r
+void cwInitCleware();\r
+int    cwOpenCleware(const char *path);        // returns number of found Cleware devices\r
+int cwRecover(int devNo);\r
+void cwCloseCleware();\r
+int    cwGetValue(int deviceNo, unsigned char *buf, int bufsize);\r
+int    cwSetValue(int deviceNo, unsigned char *buf, int bufsize);\r
+hid_device * cwGetHandle(int deviceNo);\r
+int    cwGetVersion(int deviceNo);\r
+int    cwGetSerialNumber(int deviceNo);\r
+enum USBtype_enum      cwGetUSBType(int deviceNo);\r
+int                                                    cwValidSerNum(int SerialNumber, enum USBtype_enum devType) ;\r
+void                                           cwDebugWrite(char *s) ;\r
+void                                           cwDebugClose() ;\r
+int cwGetHWversion(int deviceNo);\r
+int                                                    cwIOX(int deviceNo, int addr, int data) ;\r
+\r
+#endif // __USBACCESS_H__\r
diff --git a/circle.yml b/circle.yml
new file mode 100644 (file)
index 0000000..1ec501c
--- /dev/null
@@ -0,0 +1,70 @@
+machine:
+  timezone:
+    Europe/Vienna
+  environment:
+    _SDK_: /usr/local/android-sdk-linux/
+    PKG_CONFIG_PATH: /usr/lib/x86_64-linux-gnu/pkgconfig
+dependencies:
+  override:
+    - echo dummy
+  pre:
+    - sudo apt-get update > /dev/null 2> /dev/null
+    - sudo apt-get install telnet > /dev/null 2> /dev/null
+    - sudo apt-get install x11-utils > /dev/null 2> /dev/null
+    - sudo apt-get install xvkbd > /dev/null 2> /dev/null
+    - sudo apt-get install swig
+    - sudo apt-get install libusb-dev
+    - sudo apt-get install python-dev ; exit 0
+
+# install libhidapi ----------------
+    - cp /etc/apt/sources.list /tmp/aa
+    - echo 'deb http://cz.archive.ubuntu.com/ubuntu trusty main universe' >> /tmp/aa
+    - cat /tmp/aa; ls -al /etc/apt/sources.list /tmp/aa
+    - sudo cp -v /tmp/aa /etc/apt/sources.list
+    - sudo apt-get update
+    - sudo apt-get install libhidapi-dev
+    - dpkg-query -L libhidapi-dev
+    - sudo cp -av /usr/lib/x86_64-linux-gnu/pkgconfig/hidapi-libusb.pc /usr/lib/x86_64-linux-gnu/pkgconfig/hidapi.pc
+    - pkg-config --cflags hidapi ; exit 0
+    - pkg-config --libs hidapi ; exit 0
+# install libhidapi ----------------
+
+# --- binary ---
+    - make
+    - sudo make install
+    - cp -av clewarecontrol $CIRCLE_ARTIFACTS/clewarecontrol_$CIRCLE_SHA1 || exit 1
+# --- binary ---
+
+# --- perl extension ---
+    - sed -i -e 's#.o -o cle#.o -lhidapi-libusb -o cle#' Makefile # add hidapi-libusb to perl compile command!!
+    - sudo -- sh -c "make cleware_perl"
+    - mkdir $CIRCLE_ARTIFACTS/perl
+    - cp -av cleware.so $CIRCLE_ARTIFACTS/perl/ || exit 1
+    - ldd cleware.so
+    - cp -av cleware.pm $CIRCLE_ARTIFACTS/perl/ || exit 1
+# --- perl extension ---
+
+# --- python extension ---
+    - cp setup.py_CI setup.py # use setup file with added libs
+    - sudo make clean
+    - sudo -- sh -c "make cleware_python"
+    - mkdir $CIRCLE_ARTIFACTS/python
+    - cp -av cleware.py $CIRCLE_ARTIFACTS/python/ || exit 1
+    - cp -av _cleware.so $CIRCLE_ARTIFACTS/python/ || exit 1
+    - ldd _cleware.so
+# --- python extension ---
+
+    - make # make binary again
+    - ls -al
+
+test:
+  pre:
+    - echo 'mtools_skip_check=1' > ~/.mtoolsrc
+  override:
+    - ./clewarecontrol -l # test binary
+
+    - printf 'import cleware \n' | python # test python extension
+    - ./example.py
+    
+    - printf 'use Module::Load; \n load cleware; \n '|perl -w # test perl module
+    - ./example.pl
diff --git a/cleware.i b/cleware.i
new file mode 100644 (file)
index 0000000..76ded4b
--- /dev/null
+++ b/cleware.i
@@ -0,0 +1,252 @@
+%module cleware\r
+%{\r
+typedef int HANDLE ;\r
+\r
+const int USBaccessVersion = 330 ;\r
+\r
+#define CLEWARE_DEBUG 1\r
+\r
+#define INVALID_HANDLE_VALUE -1\r
+\r
+enum USBtype_enum {    ILLEGAL_DEVICE=0,\r
+                                               LED_DEVICE=0x01,\r
+                                               POWER_DEVICE=0x02,\r
+                                               DISPLAY_DEVICE=0x03,\r
+                                               WATCHDOG_DEVICE=0x05,\r
+                                               AUTORESET_DEVICE=0x06,\r
+                                               WATCHDOGXP_DEVICE=0x07,\r
+                                               SWITCH1_DEVICE=0x08,\r
+                                               SWITCH2_DEVICE=0x09, SWITCH3_DEVICE=0x0a, SWITCH4_DEVICE=0x0b,\r
+                                               SWITCH5_DEVICE=0x0c, SWITCH6_DEVICE=0x0d, SWITCH7_DEVICE=0x0e, SWITCH8_DEVICE=0x0f,\r
+                                               TEMPERATURE_DEVICE=0x10,\r
+                                               TEMPERATURE2_DEVICE=0x11,\r
+                                               TEMPERATURE5_DEVICE=0x15, \r
+                                               HUMIDITY1_DEVICE=0x20,HUMIDITY2_DEVICE=0x21,\r
+                                               SWITCHX_DEVICE=0x28,            // new switch 3,4,8\r
+                                               // CONTACT1_DEVICE=0x30 \r
+                                               CONTACT00_DEVICE=0x30, CONTACT01_DEVICE=0x31, CONTACT02_DEVICE=0x32, CONTACT03_DEVICE=0x33, \r
+                                               CONTACT04_DEVICE=0x34, CONTACT05_DEVICE=0x35, CONTACT06_DEVICE=0x36, CONTACT07_DEVICE=0x37, \r
+                                               CONTACT08_DEVICE=0x38, CONTACT09_DEVICE=0x39, CONTACT10_DEVICE=0x3a, CONTACT11_DEVICE=0x3b, \r
+                                               CONTACT12_DEVICE=0x3c, CONTACT13_DEVICE=0x3d, CONTACT14_DEVICE=0x3e, CONTACT15_DEVICE=0x3f, \r
+                                               F4_DEVICE=0x40, \r
+                                               KEYC01_DEVICE=0x41, KEYC16_DEVICE=0x42,MOUSE_DEVICE=0x43,\r
+                                               ADC0800_DEVICE=0x50, ADC0801_DEVICE=0x51, ADC0802_DEVICE=0x52, ADC0803_DEVICE=0x53, \r
+                                               COUNTER00_DEVICE=0x60, \r
+                                               ENCODER01_DEVICE=0x80,\r
+                                               BUTTON_NODEVICE=0x1000\r
+                                               } ;\r
+enum USBactions {              LEDs=0, EEwrite=1, EEread=2, Reset=3, KeepCalm=4, GetInfo=5, \r
+                                               StartMeasuring=6,               // USB-Humidity\r
+                                               Configure=7,                    // USB-IO16-V10, USB-Counter-V05\r
+                                               Display=8,                              // USB/Display\r
+                                               RunPoint=10,                    // USB-Encoder\r
+                                               Programm=15                             // Transfer new Firmware (internal use only)\r
+                                               } ;\r
+\r
+// 03.11.02    ws      small changes for Linux\r
+typedef struct {\r
+       unsigned long int       handle ;\r
+       int                                     gadgetVersionNo ;\r
+       enum USBtype_enum       gadgettype ;\r
+       int                                     SerialNumber ;\r
+       int                                     report_type ;\r
+       int                                     HWversion ;\r
+       } cwSUSBdata ;\r
+\r
+\r
+void                                           cwInitCleware() ;\r
+int                                                    cwOpenCleware() ;       // returns number of found Cleware devices\r
+void                                           cwCloseCleware() ;\r
+int                                                    cwGetValue(int deviceNo, int UsagePage, int Usage, unsigned char *buf, int bufsize) ;\r
+int                                                    cwSetValue(int deviceNo, int UsagePage, int Usage, unsigned char *buf, int bufsize) ;\r
+unsigned long int                      cwGetHandle(int deviceNo) ;\r
+int                                                    cwGetVersion(int deviceNo) ;\r
+enum USBtype_enum                      cwGetUSBType(int deviceNo) ;\r
+int                                                    cwGetSerialNumber(int deviceNo) ;\r
+int                                                    cwRecover(int devNum) ;         // try to find disconnected devices\r
+int                                                    cwValidSerNum(int SerialNumber, enum USBtype_enum devType) ;\r
+int                                                    cwGetHWversion(int deviceNo) ;                  // return current\r
+int                                                    cwIOX(int deviceNo, int addr, int data) ;\r
+void                                           cwDebugWrite(char *s) ;\r
+void                                           cwDebugClose() ;\r
+\r
+class CUSBaccess {\r\r
+       public:\r\r
+               enum USBactions {               LEDs=0, EEwrite=1, EEread=2, Reset=3, KeepCalm=4, GetInfo=5, \r\r
+                                                               StartMeasuring=6,               // USB-Humidity\r\r
+                                                               Configure=7,                    // USB-IO16-V10, USB-Counter-V05\r\r
+                                                               RunPoint=10,                    // USB-Encoder\r\r
+                                                               ContactWrite=11,                // 613er IO16\r\r
+                                                               ContactRead=12                  // 613er IO16\r\r
+                                                               } ;\r\r
+               enum USBInfoType {              OnlineTime=1, OnlineCount=2, ManualTime=3, ManualCount=4 } ;\r\r
+               enum LED_IDs {                  LED_0=0, LED_1=1, LED_2=2, LED_3=3 } ;\r\r
+               enum COUNTER_IDs {              COUNTER_0=0, COUNTER_1=1 } ;\r\r
+               enum SWITCH_IDs {               SWITCH_0=0x10, SWITCH_1=0x11, SWITCH_2=0x12, SWITCH_3=0x13,\r\r
+                                                               SWITCH_4=0x14, SWITCH_5=0x15, SWITCH_6=0x16, SWITCH_7=0x17,\r\r
+                                                               SWITCH_8=0x18, SWITCH_9=0x19, SWITCH_10=0x1a, SWITCH_11=0x1b,\r\r
+                                                               SWITCH_12=0x1c, SWITCH_13=0x1d, SWITCH_14=0x1e, SWITCH_15=0x1f\r\r
+                                                               } ;\r\r
+               enum USBtype_enum {             ILLEGAL_DEVICE=0,\r\r
+                                                               LED_DEVICE=0x01,\r\r
+                                                               POWER_DEVICE=0x02,\r\r
+                                                               WATCHDOG_DEVICE=0x05,\r\r
+                                                               AUTORESET_DEVICE=0x06,\r\r
+                                                               WATCHDOGXP_DEVICE=0x07,\r\r
+                                                               SWITCH1_DEVICE=0x08,\r\r
+                                                               SWITCH2_DEVICE=0x09, SWITCH3_DEVICE=0x0a, SWITCH4_DEVICE=0x0b,\r\r
+                                                               SWITCH5_DEVICE=0x0c, SWITCH6_DEVICE=0x0d, SWITCH7_DEVICE=0x0e, SWITCH8_DEVICE=0x0f,\r\r
+                                                               TEMPERATURE_DEVICE=0x10, \r\r
+                                                               TEMPERATURE2_DEVICE=0x11,\r\r
+                                                               TEMPERATURE5_DEVICE=0x15, \r\r
+                                                               HUMIDITY1_DEVICE=0x20,\r\r
+                                                               SWITCHX_DEVICE=0x28,            // new switch 3,4,8\r\r
+                                                               CONTACT00_DEVICE=0x30, CONTACT01_DEVICE=0x31, CONTACT02_DEVICE=0x32, CONTACT03_DEVICE=0x33, \r\r
+                                                               CONTACT04_DEVICE=0x34, CONTACT05_DEVICE=0x35, CONTACT06_DEVICE=0x36, CONTACT07_DEVICE=0x37, \r\r
+                                                               CONTACT08_DEVICE=0x38, CONTACT09_DEVICE=0x39, CONTACT10_DEVICE=0x3a, CONTACT11_DEVICE=0x3b, \r\r
+                                                               CONTACT12_DEVICE=0x3c, CONTACT13_DEVICE=0x3d, CONTACT14_DEVICE=0x3e, CONTACT15_DEVICE=0x3f, \r\r
+                                                               F4_DEVICE=0x40, \r\r
+                                                               KEYC01_DEVICE=0x41, KEYC16_DEVICE=0x42,\r\r
+                                                               ADC0800_DEVICE=0x50, ADC0801_DEVICE=0x51, ADC0802_DEVICE=0x52, ADC0803_DEVICE=0x53, \r\r
+                                                               COUNTER00_DEVICE=0x60, \r\r
+                                                               ENCODER01_DEVICE=0x80,\r\r
+                                                               BUTTON_NODEVICE=0x1000\r\r
+                                                               } ;\r\r
+       private:\r\r
+               class CUSBaccessBasic * X       ;       // avoid export of internal USB variables\r\r
+\r\r
+       public:\r\r
+               CUSBaccess() ;\r\r
+               virtual ~CUSBaccess() ;         // maybe used as base class\r\r
+\r\r
+               virtual int                     OpenCleware() ;                 // returns number of found Cleware devices\r\r
+               virtual int                     CloseCleware() ;                // close all Cleware devices\r\r
+               virtual int                     Recover(int devNum) ;   // try to find disconnected devices, returns true if succeeded\r\r
+               virtual HANDLE          GetHandle(int deviceNo) ;\r\r
+               virtual int                     GetValue(int deviceNo, unsigned char *buf, int bufsize) ;\r\r
+               virtual int                     SetValue(int deviceNo, unsigned char *buf, int bufsize) ;\r\r
+               virtual int                     SetLED(int deviceNo, enum LED_IDs Led, int value) ;     // value: 0=off 7=medium 15=highlight\r\r
+               virtual int                     SetSwitch(int deviceNo, enum SWITCH_IDs Switch, int On) ;       //      On: 0=off, 1=on\r\r
+               virtual int                     GetSwitch(int deviceNo, enum SWITCH_IDs Switch) ;                       //      On: 0=off, 1=on, -1=error\r\r
+               virtual int                     GetSeqSwitch(int deviceNo, enum SWITCH_IDs Switch, int seqNum) ;                //      On: 0=off, 1=on, -1=error\r\r
+               virtual int                     GetSwitchConfig(int deviceNo, int *switchCount, int *buttonAvailable) ;\r\r
+               virtual int                     GetTemperature(int deviceNo, double *Temperature, int *timeID) ;\r\r
+               virtual int                     GetHumidity(int deviceNo, double *Humidity, int *timeID) ;\r\r
+               virtual int                     ResetDevice(int deviceNo) ;\r\r
+               virtual int                     StartDevice(int deviceNo) ;     \r\r
+               virtual int                     CalmWatchdog(int deviceNo, int minutes, int minutes2restart) ;\r\r
+               virtual int                     GetVersion(int deviceNo) ;\r\r
+               virtual int                     GetUSBType(int deviceNo) ;\r\r
+               virtual int                     GetSerialNumber(int deviceNo) ;\r\r
+               virtual int                     GetDLLVersion() { return USBaccessVersion ; }\r\r
+               virtual int                     GetManualOnCount(int deviceNo) ;                // returns how often switch is manually turned on\r\r
+               virtual int                     GetManualOnTime(int deviceNo) ;                 // returns how long (seconds) switch is manually turned on\r\r
+               virtual int                     GetOnlineOnCount(int deviceNo) ;                // returns how often switch is turned on by USB command\r\r
+               virtual int                     GetOnlineOnTime(int deviceNo) ;                 // returns how long (seconds) switch is turned on by USB command\r\r
+               virtual int                     GetMultiSwitch(int deviceNo, unsigned long int *mask, unsigned long int *value, int seqNumber) ;\r\r
+               virtual int                     SetMultiSwitch(int deviceNo, unsigned long int value) ;\r\r
+               virtual int                     SetMultiConfig(int deviceNo, unsigned long int directions) ;\r\r
+               virtual int                     GetCounter(int deviceNo, enum COUNTER_IDs counterID) ;  // COUNTER_IDs ununsed until now\r\r
+               virtual int                     SetCounter(int deviceNo, int counter, enum COUNTER_IDs counterID) ;     //  -1=error, COUNTER_IDs ununsed until now\r\r
+               virtual int                     SyncDevice(int deviceNo, unsigned long int mask) ;\r\r
+               virtual int                     GetHWversion(int deviceNo) ;    // return HWversion (0 for pre 2014 designed devices, 13 for new devices)\r\r
+               virtual int                     IOX(int deviceNo, int addr, int data) ;         // for internal use only, wrong usage may destroy device        \r\r
+               virtual void            DebugWrite(char *s) ;\r\r
+               virtual void            DebugWrite(char *f, int a1) ;\r\r
+               virtual void            DebugWrite(char *f, int a1, int a2) ;\r\r
+               virtual void            DebugWrite(char *f, int a1, int a2, int a3) ;\r\r
+               virtual void            DebugWrite(char *f, int a1, int a2, int a3, int a4) ;\r\r
+               virtual void            Sleep(int ms) { usleep(ms * 1000) ; }   // for Linux\r\r
+       } ;\r\r
+%}\r
+\r
+const int USBaccessVersion = 433 ;\r\r
+\r\r
+class CUSBaccess {\r\r
+       public:\r\r
+               enum USBactions {               LEDs=0, EEwrite=1, EEread=2, Reset=3, KeepCalm=4, GetInfo=5, \r\r
+                                                               StartMeasuring=6,               // USB-Humidity\r\r
+                                                               Configure=7,                    // USB-IO16-V10, USB-Counter-V05\r\r
+                                                               RunPoint=10,                    // USB-Encoder\r\r
+                                                               ContactWrite=11,                // 613er IO16\r\r
+                                                               ContactRead=12                  // 613er IO16\r\r
+                                                               } ;\r\r
+               enum USBInfoType {              OnlineTime=1, OnlineCount=2, ManualTime=3, ManualCount=4 } ;\r\r
+               enum LED_IDs {                  LED_0=0, LED_1=1, LED_2=2, LED_3=3 } ;\r\r
+               enum COUNTER_IDs {              COUNTER_0=0, COUNTER_1=1 } ;\r\r
+               enum SWITCH_IDs {               SWITCH_0=0x10, SWITCH_1=0x11, SWITCH_2=0x12, SWITCH_3=0x13,\r\r
+                                                               SWITCH_4=0x14, SWITCH_5=0x15, SWITCH_6=0x16, SWITCH_7=0x17,\r\r
+                                                               SWITCH_8=0x18, SWITCH_9=0x19, SWITCH_10=0x1a, SWITCH_11=0x1b,\r\r
+                                                               SWITCH_12=0x1c, SWITCH_13=0x1d, SWITCH_14=0x1e, SWITCH_15=0x1f\r\r
+                                                               } ;\r\r
+               enum USBtype_enum {             ILLEGAL_DEVICE=0,\r\r
+                                                               LED_DEVICE=0x01,\r\r
+                                                               POWER_DEVICE=0x02,\r\r
+                                                               WATCHDOG_DEVICE=0x05,\r\r
+                                                               AUTORESET_DEVICE=0x06,\r\r
+                                                               WATCHDOGXP_DEVICE=0x07,\r\r
+                                                               SWITCH1_DEVICE=0x08,\r\r
+                                                               SWITCH2_DEVICE=0x09, SWITCH3_DEVICE=0x0a, SWITCH4_DEVICE=0x0b,\r\r
+                                                               SWITCH5_DEVICE=0x0c, SWITCH6_DEVICE=0x0d, SWITCH7_DEVICE=0x0e, SWITCH8_DEVICE=0x0f,\r\r
+                                                               TEMPERATURE_DEVICE=0x10, \r\r
+                                                               TEMPERATURE2_DEVICE=0x11,\r\r
+                                                               TEMPERATURE5_DEVICE=0x15, \r\r
+                                                               HUMIDITY1_DEVICE=0x20,\r\r
+                                                               SWITCHX_DEVICE=0x28,            // new switch 3,4,8\r\r
+                                                               CONTACT00_DEVICE=0x30, CONTACT01_DEVICE=0x31, CONTACT02_DEVICE=0x32, CONTACT03_DEVICE=0x33, \r\r
+                                                               CONTACT04_DEVICE=0x34, CONTACT05_DEVICE=0x35, CONTACT06_DEVICE=0x36, CONTACT07_DEVICE=0x37, \r\r
+                                                               CONTACT08_DEVICE=0x38, CONTACT09_DEVICE=0x39, CONTACT10_DEVICE=0x3a, CONTACT11_DEVICE=0x3b, \r\r
+                                                               CONTACT12_DEVICE=0x3c, CONTACT13_DEVICE=0x3d, CONTACT14_DEVICE=0x3e, CONTACT15_DEVICE=0x3f, \r\r
+                                                               F4_DEVICE=0x40, \r\r
+                                                               KEYC01_DEVICE=0x41, KEYC16_DEVICE=0x42,\r\r
+                                                               ADC0800_DEVICE=0x50, ADC0801_DEVICE=0x51, ADC0802_DEVICE=0x52, ADC0803_DEVICE=0x53, \r\r
+                                                               COUNTER00_DEVICE=0x60, \r\r
+                                                               ENCODER01_DEVICE=0x80,\r\r
+                                                               BUTTON_NODEVICE=0x1000\r\r
+                                                               } ;\r\r
+       private:\r\r
+               class CUSBaccessBasic * X       ;       // avoid export of internal USB variables\r\r
+\r\r
+       public:\r\r
+               CUSBaccess() ;\r\r
+               virtual ~CUSBaccess() ;         // maybe used as base class\r\r
+\r\r
+               virtual int                     OpenCleware() ;                 // returns number of found Cleware devices\r\r
+               virtual int                     CloseCleware() ;                // close all Cleware devices\r\r
+               virtual int                     Recover(int devNum) ;   // try to find disconnected devices, returns true if succeeded\r\r
+               virtual HANDLE          GetHandle(int deviceNo) ;\r\r
+               virtual int                     GetValue(int deviceNo, unsigned char *buf, int bufsize) ;\r\r
+               virtual int                     SetValue(int deviceNo, unsigned char *buf, int bufsize) ;\r\r
+               virtual int                     SetLED(int deviceNo, enum LED_IDs Led, int value) ;     // value: 0=off 7=medium 15=highlight\r\r
+               virtual int                     SetSwitch(int deviceNo, enum SWITCH_IDs Switch, int On) ;       //      On: 0=off, 1=on\r\r
+               virtual int                     GetSwitch(int deviceNo, enum SWITCH_IDs Switch) ;                       //      On: 0=off, 1=on, -1=error\r\r
+               virtual int                     GetSeqSwitch(int deviceNo, enum SWITCH_IDs Switch, int seqNum) ;                //      On: 0=off, 1=on, -1=error\r\r
+               virtual int                     GetSwitchConfig(int deviceNo, int *switchCount, int *buttonAvailable) ;\r\r
+               virtual int                     GetTemperature(int deviceNo, double *Temperature, int *timeID) ;\r\r
+               virtual int                     GetHumidity(int deviceNo, double *Humidity, int *timeID) ;\r\r
+               virtual int                     ResetDevice(int deviceNo) ;\r\r
+               virtual int                     StartDevice(int deviceNo) ;     \r\r
+               virtual int                     CalmWatchdog(int deviceNo, int minutes, int minutes2restart) ;\r\r
+               virtual int                     GetVersion(int deviceNo) ;\r\r
+               virtual int                     GetUSBType(int deviceNo) ;\r\r
+               virtual int                     GetSerialNumber(int deviceNo) ;\r\r
+               virtual int                     GetDLLVersion() { return USBaccessVersion ; }\r\r
+               virtual int                     GetManualOnCount(int deviceNo) ;                // returns how often switch is manually turned on\r\r
+               virtual int                     GetManualOnTime(int deviceNo) ;                 // returns how long (seconds) switch is manually turned on\r\r
+               virtual int                     GetOnlineOnCount(int deviceNo) ;                // returns how often switch is turned on by USB command\r\r
+               virtual int                     GetOnlineOnTime(int deviceNo) ;                 // returns how long (seconds) switch is turned on by USB command\r\r
+               virtual int                     GetMultiSwitch(int deviceNo, unsigned long int *mask, unsigned long int *value, int seqNumber) ;\r\r
+               virtual int                     SetMultiSwitch(int deviceNo, unsigned long int value) ;\r\r
+               virtual int                     SetMultiConfig(int deviceNo, unsigned long int directions) ;\r\r
+               virtual int                     GetCounter(int deviceNo, enum COUNTER_IDs counterID) ;  // COUNTER_IDs ununsed until now\r\r
+               virtual int                     SetCounter(int deviceNo, int counter, enum COUNTER_IDs counterID) ;     //  -1=error, COUNTER_IDs ununsed until now\r\r
+               virtual int                     SyncDevice(int deviceNo, unsigned long int mask) ;\r\r
+               virtual int                     GetHWversion(int deviceNo) ;    // return HWversion (0 for pre 2014 designed devices, 13 for new devices)\r\r
+               virtual int                     IOX(int deviceNo, int addr, int data) ;         // for internal use only, wrong usage may destroy device        \r\r
+               virtual void            DebugWrite(char *s) ;\r\r
+               virtual void            DebugWrite(char *f, int a1) ;\r\r
+               virtual void            DebugWrite(char *f, int a1, int a2) ;\r\r
+               virtual void            DebugWrite(char *f, int a1, int a2, int a3) ;\r\r
+               virtual void            DebugWrite(char *f, int a1, int a2, int a3, int a4) ;\r\r
+               virtual void            Sleep(int ms) { usleep(ms * 1000) ; }   // for Linux\r\r
+       } ;\r\r
diff --git a/clewarecontrol.1 b/clewarecontrol.1
new file mode 100644 (file)
index 0000000..eb86c16
--- /dev/null
@@ -0,0 +1,110 @@
+.\" Copyright Folkert van Heusden, 2005
+.\"
+.\" This file may be copied under the conditions described
+.\" in the GNU GENERAL PUBLIC LICENSE, Version 1, September 1998
+.\" that should have been distributed together with this file.
+.\"
+.TH CLEWARECONTROL 1 2005-06 "clewarecontrol"
+.SH NAME
+clewarecontrol \- control the USB devices made by Cleware GmbH
+.SH SYNOPSIS
+.BI "clewarecontrol [" options "]
+.sp
+options:
+.BI "[\-l] [\-d serialnr] [\-c retrycount] [\-rt] [\-rs switchnr] [\-ar] [\-as switch state] [\-ag] [\-al led state] [\-w] [\-rp] [\-b] [\-o offset]"
+.sp
+.SH DESCRIPTION
+The program
+.B clewarecontrol
+lets you control all USB devices created by Cleware GmbH. Measuring the temperature, switching a led on or off, etc.
+.PP
+.SH OPTIONS
+.TP
+.B "\-p"
+Directory where to look for the 'hiddev'-devices. Normally this is in /dev/usb (default location) but with -p you can also select e.g. /dev When using this switch, put it in front of all other commandlineswitches.
+.TP
+.B "\-l"
+Lists all Cleware GmbH devices and their capabilities.
+.TP
+.B "\-d serialnr"
+Selects the device to control by its serial number. You can find the serial number on the USB-connector as well as with the 
+.BI "\-l"
+switch.
+.TP
+.B "\-c retrycount"
+Sometimes commands to a device seem to fail. With this switch you can set the number of retries. The default is 10.
+.TP
+.B "\-o offset"
+Adds an offset value to the temperature/humidity (in case the sensor returns a too low/high value).
+.TP
+.B "\-rt"
+Shows the temperature measured by a device capable of doing so.
+.TP
+.B "\-rh"
+Shows the humidity measured by a device capable of doing so.
+.TP
+.B "\-rs x"
+Shows the state of switch
+.BI "x"
+of a device which has switches.
+.TP
+.B "\-ar"
+Resets a device.
+.TP
+.B "\-ag"
+Starts a device (for example the humidity sensor).
+.TP
+.B "\-w"
+With this switch the program will become a daemon process which keeps the watchdog happy. If the program is terminated or freezes, the watchdog will reboot the computer.
+.TP
+.B "\-as switch state"
+Switches the switch with number
+.BI "switch"
+to the state given with
+.BI "state"
+0=off, 1=on. For a 'USB Ampel' the switch-number is 0 for red, 1 for yellow and 2 for green.
+.TP
+.B "\-al led state"
+Switches the led with number
+.BI "led"
+to the state given with
+.BI "state"
+State can be a value in the range 0...15.
+.TP
+.B "\-am state"
+Sets the states of the USB-IO16 lines.
+.BI "state"
+must be a hex value.
+.TP
+.B "\-ad state"
+Sets the direction of the lines of the USB-IO16 lines.
+.BI "state"
+must be a hex value. A bit set to 0 means input, a bit set to 1 means output.
+.TP
+.B "\-rp"
+Shows how many times the external switch (USB-Plug) was switched on manually. Also displays how long the switch is set to on.
+.TP
+.B "\-rr"
+Shows how many times the auto-reset kicked in.
+.TP
+.B "\-b"
+Brief output, better parseable for scripts.
+.TP
+.B "\-h"
+Shows a list of commandline switches.
+.TP
+.B "\-V"
+Show the version and exit.
+
+.SH BUGS
+None. This program is totally bug-free.
+
+.SH "SEE ALSO"
+.BR http://www.vanheusden.com/clewarecontrol/
+
+.SH NOTES
+This page describes
+.B clewarecontrol
+as found in the clewarecontrol-1.0 package; other versions may differ slightly.
+Mail corrections and additions to folkert@vanheusden.com.
+Report bugs in the program to folkert@vanheusden.com.
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..d0eeaee
--- /dev/null
@@ -0,0 +1,5 @@
+clewarecontrol (4.3-1) unstable; urgency=low
+
+  * Initial release
+
+ -- Donghoon Shin <dhs.shin@samsung.com>  Mon, 30 May 2016 11:49:42 +0900
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..ec63514
--- /dev/null
@@ -0,0 +1 @@
+9
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..c6033d3
--- /dev/null
@@ -0,0 +1,14 @@
+Source: clewarecontrol
+Section: devel
+Priority: optional
+Maintainer: Donghoon Shin <dhs.shin@samsung.com>
+XSBC-Original-Maintainer: Folkert van Heusden <folkert@vanheusden.com>
+Build-Depends: debhelper (>= 8.0.0), libhidapi-dev (>= 0.8), pkg-config (>= 0.26)
+Standards-Version: 3.9.4
+Homepage: https://github.com/flok99/clewarecontrol
+
+Package: clewarecontrol
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: A program to control devices by Cleware
+ control the USB devices made by Cleware GmbH.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..8cf23f1
--- /dev/null
@@ -0,0 +1,638 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: clewarecontrol
+Source: https://github.com/flok99/clewarecontrol
+
+Upstream Authors:
+ Folkert van Heusden <folkert@vanheusden.com>
+
+Copyright:
+ 2005-2013 by folkert@vanheusden.com
+ (C) 2001 Copyright Cleware GmbH
+ (C) 2001-2014 Copyright Cleware GmbH
+ Alan Ott, Signal 11 Software Copyright 2009, All Rights Reserved.
+ Alan Ott, Signal 11 Software Copyright 2010, All Rights Reserved.
+
+License: AGPL-3
+
+Files: debian/*
+Copyright: 2016 Donghoon Shin <dhs.shin@samsung.com>
+License: AGPL-3
+
+License: AGPL-3
+ GNU AFFERO GENERAL PUBLIC LICENSE
+ Version 3, 19 November 2007
+ .
+ Copyright (C) 2007 Free Software Foundation, Inc. 
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+ .
+ Preamble
+ .
+ The GNU Affero General Public License is a free, copyleft license for
+ software and other kinds of works, specifically designed to ensure
+ cooperation with the community in the case of network server software.
+ .
+ The licenses for most software and other practical works are designed
+ to take away your freedom to share and change the works.  By contrast,
+ our General Public Licenses are intended to guarantee your freedom to
+ share and change all versions of a program--to make sure it remains free
+ software for all its users.
+ .
+ When we speak of free software, we are referring to freedom, not
+ price.  Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ them if you wish), that you receive source code or can get it if you
+ want it, that you can change the software or use pieces of it in new
+ free programs, and that you know you can do these things.
+ .
+ Developers that use our General Public Licenses protect your rights
+ with two steps: (1) assert copyright on the software, and (2) offer
+ you this License which gives you legal permission to copy, distribute
+ and/or modify the software.
+ .
+ A secondary benefit of defending all users' freedom is that
+ improvements made in alternate versions of the program, if they
+ receive widespread use, become available for other developers to
+ incorporate.  Many developers of free software are heartened and
+ encouraged by the resulting cooperation.  However, in the case of
+ software used on network servers, this result may fail to come about.
+ The GNU General Public License permits making a modified version and
+ letting the public access it on a server without ever releasing its
+ source code to the public.
+ .
+ The GNU Affero General Public License is designed specifically to
+ ensure that, in such cases, the modified source code becomes available
+ to the community.  It requires the operator of a network server to
+ provide the source code of the modified version running there to the
+ users of that server.  Therefore, public use of a modified version, on
+ a publicly accessible server, gives the public access to the source
+ code of the modified version.
+ .
+ An older license, called the Affero General Public License and
+ published by Affero, was designed to accomplish similar goals.  This is
+ a different license, not a version of the Affero GPL, but Affero has
+ released a new version of the Affero GPL which permits relicensing under
+ this license.
+ .
+ The precise terms and conditions for copying, distribution and
+ modification follow.
+ .
+ TERMS AND CONDITIONS
+ .
+ 0. Definitions.
+ .
+ "This License" refers to version 3 of the GNU Affero General Public License.
+ .
+ "Copyright" also means copyright-like laws that apply to other kinds of
+ works, such as semiconductor masks.
+ .
+ "The Program" refers to any copyrightable work licensed under this
+ License.  Each licensee is addressed as "you".  "Licensees" and
+ "recipients" may be individuals or organizations.
+ .
+ To "modify" a work means to copy from or adapt all or part of the work
+ in a fashion requiring copyright permission, other than the making of an
+ exact copy.  The resulting work is called a "modified version" of the
+ earlier work or a work "based on" the earlier work.
+ .
+ A "covered work" means either the unmodified Program or a work based
+ on the Program.
+ .
+ To "propagate" a work means to do anything with it that, without
+ permission, would make you directly or secondarily liable for
+ infringement under applicable copyright law, except executing it on a
+ computer or modifying a private copy.  Propagation includes copying,
+ distribution (with or without modification), making available to the
+ public, and in some countries other activities as well.
+ .
+ To "convey" a work means any kind of propagation that enables other
+ parties to make or receive copies.  Mere interaction with a user through
+ a computer network, with no transfer of a copy, is not conveying.
+ .
+ An interactive user interface displays "Appropriate Legal Notices"
+ to the extent that it includes a convenient and prominently visible
+ feature that (1) displays an appropriate copyright notice, and (2)
+ tells the user that there is no warranty for the work (except to the
+ extent that warranties are provided), that licensees may convey the
+ work under this License, and how to view a copy of this License.  If
+ the interface presents a list of user commands or options, such as a
+ menu, a prominent item in the list meets this criterion.
+ .
+ 1. Source Code.
+ .
+ The "source code" for a work means the preferred form of the work
+ for making modifications to it.  "Object code" means any non-source
+ form of a work.
+ .
+ A "Standard Interface" means an interface that either is an official
+ standard defined by a recognized standards body, or, in the case of
+ interfaces specified for a particular programming language, one that
+ is widely used among developers working in that language.
+ .
+ The "System Libraries" of an executable work include anything, other
+ than the work as a whole, that (a) is included in the normal form of
+ packaging a Major Component, but which is not part of that Major
+ Component, and (b) serves only to enable use of the work with that
+ Major Component, or to implement a Standard Interface for which an
+ implementation is available to the public in source code form.  A
+ "Major Component", in this context, means a major essential component
+ (kernel, window system, and so on) of the specific operating system
+ (if any) on which the executable work runs, or a compiler used to
+ produce the work, or an object code interpreter used to run it.
+ .
+ The "Corresponding Source" for a work in object code form means all
+ the source code needed to generate, install, and (for an executable
+ work) run the object code and to modify the work, including scripts to
+ control those activities.  However, it does not include the work's
+ System Libraries, or general-purpose tools or generally available free
+ programs which are used unmodified in performing those activities but
+ which are not part of the work.  For example, Corresponding Source
+ includes interface definition files associated with source files for
+ the work, and the source code for shared libraries and dynamically
+ linked subprograms that the work is specifically designed to require,
+ such as by intimate data communication or control flow between those
+ subprograms and other parts of the work.
+ .
+ The Corresponding Source need not include anything that users
+ can regenerate automatically from other parts of the Corresponding
+ Source.
+ .
+ The Corresponding Source for a work in source code form is that
+ same work.
+ .
+ 2. Basic Permissions.
+ .
+ All rights granted under this License are granted for the term of
+ copyright on the Program, and are irrevocable provided the stated
+ conditions are met.  This License explicitly affirms your unlimited
+ permission to run the unmodified Program.  The output from running a
+ covered work is covered by this License only if the output, given its
+ content, constitutes a covered work.  This License acknowledges your
+ rights of fair use or other equivalent, as provided by copyright law.
+ .
+ You may make, run and propagate covered works that you do not
+ convey, without conditions so long as your license otherwise remains
+ in force.  You may convey covered works to others for the sole purpose
+ of having them make modifications exclusively for you, or provide you
+ with facilities for running those works, provided that you comply with
+ the terms of this License in conveying all material for which you do
+ not control copyright.  Those thus making or running the covered works
+ for you must do so exclusively on your behalf, under your direction
+ and control, on terms that prohibit them from making any copies of
+ your copyrighted material outside their relationship with you.
+ .
+ Conveying under any other circumstances is permitted solely under
+ the conditions stated below.  Sublicensing is not allowed; section 10
+ makes it unnecessary.
+ .
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+ .
+ No covered work shall be deemed part of an effective technological
+ measure under any applicable law fulfilling obligations under article
+ 11 of the WIPO copyright treaty adopted on 20 December 1996, or
+ similar laws prohibiting or restricting circumvention of such
+ measures.
+ .
+ When you convey a covered work, you waive any legal power to forbid
+ circumvention of technological measures to the extent such circumvention
+ is effected by exercising rights under this License with respect to
+ the covered work, and you disclaim any intention to limit operation or
+ modification of the work as a means of enforcing, against the work's
+ users, your or third parties' legal rights to forbid circumvention of
+ technological measures.
+ .
+ 4. Conveying Verbatim Copies.
+ .
+ You may convey verbatim copies of the Program's source code as you
+ receive it, in any medium, provided that you conspicuously and
+ appropriately publish on each copy an appropriate copyright notice;
+ keep intact all notices stating that this License and any
+ non-permissive terms added in accord with section 7 apply to the code;
+ keep intact all notices of the absence of any warranty; and give all
+ recipients a copy of this License along with the Program.
+ .
+ You may charge any price or no price for each copy that you convey,
+ and you may offer support or warranty protection for a fee.
+ .
+ 5. Conveying Modified Source Versions.
+ .
+ You may convey a work based on the Program, or the modifications to
+ produce it from the Program, in the form of source code under the
+ terms of section 4, provided that you also meet all of these conditions:
+ .
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+ .
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7.  This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+ .
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy.  This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged.  This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+ .
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+ .
+ A compilation of a covered work with other separate and independent
+ works, which are not by their nature extensions of the covered work,
+ and which are not combined with it such as to form a larger program,
+ in or on a volume of a storage or distribution medium, is called an
+ "aggregate" if the compilation and its resulting copyright are not
+ used to limit the access or legal rights of the compilation's users
+ beyond what the individual works permit.  Inclusion of a covered work
+ in an aggregate does not cause this License to apply to the other
+ parts of the aggregate.
+ .
+ 6. Conveying Non-Source Forms.
+ .
+ You may convey a covered work in object code form under the terms
+ of sections 4 and 5, provided that you also convey the
+ machine-readable Corresponding Source under the terms of this License,
+ in one of these ways:
+ .
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+ .
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+ .
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source.  This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+ .
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge.  You need not require recipients to copy the
+ Corresponding Source along with the object code.  If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source.  Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+ .
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+ .
+ A separable portion of the object code, whose source code is excluded
+ from the Corresponding Source as a System Library, need not be
+ included in conveying the object code work.
+ .
+ A "User Product" is either (1) a "consumer product", which means any
+ tangible personal property which is normally used for personal, family,
+ or household purposes, or (2) anything designed or sold for incorporation
+ into a dwelling.  In determining whether a product is a consumer product,
+ doubtful cases shall be resolved in favor of coverage.  For a particular
+ product received by a particular user, "normally used" refers to a
+ typical or common use of that class of product, regardless of the status
+ of the particular user or of the way in which the particular user
+ actually uses, or expects or is expected to use, the product.  A product
+ is a consumer product regardless of whether the product has substantial
+ commercial, industrial or non-consumer uses, unless such uses represent
+ the only significant mode of use of the product.
+ .
+ "Installation Information" for a User Product means any methods,
+ procedures, authorization keys, or other information required to install
+ and execute modified versions of a covered work in that User Product from
+ a modified version of its Corresponding Source.  The information must
+ suffice to ensure that the continued functioning of the modified object
+ code is in no case prevented or interfered with solely because
+ modification has been made.
+ .
+ If you convey an object code work under this section in, or with, or
+ specifically for use in, a User Product, and the conveying occurs as
+ part of a transaction in which the right of possession and use of the
+ User Product is transferred to the recipient in perpetuity or for a
+ fixed term (regardless of how the transaction is characterized), the
+ Corresponding Source conveyed under this section must be accompanied
+ by the Installation Information.  But this requirement does not apply
+ if neither you nor any third party retains the ability to install
+ modified object code on the User Product (for example, the work has
+ been installed in ROM).
+ .
+ The requirement to provide Installation Information does not include a
+ requirement to continue to provide support service, warranty, or updates
+ for a work that has been modified or installed by the recipient, or for
+ the User Product in which it has been modified or installed.  Access to a
+ network may be denied when the modification itself materially and
+ adversely affects the operation of the network or violates the rules and
+ protocols for communication across the network.
+ .
+ Corresponding Source conveyed, and Installation Information provided,
+ in accord with this section must be in a format that is publicly
+ documented (and with an implementation available to the public in
+ source code form), and must require no special password or key for
+ unpacking, reading or copying.
+ .
+ 7. Additional Terms.
+ .
+ "Additional permissions" are terms that supplement the terms of this
+ License by making exceptions from one or more of its conditions.
+ Additional permissions that are applicable to the entire Program shall
+ be treated as though they were included in this License, to the extent
+ that they are valid under applicable law.  If additional permissions
+ apply only to part of the Program, that part may be used separately
+ under those permissions, but the entire Program remains governed by
+ this License without regard to the additional permissions.
+ .
+ When you convey a copy of a covered work, you may at your option
+ remove any additional permissions from that copy, or from any part of
+ it.  (Additional permissions may be written to require their own
+ removal in certain cases when you modify the work.)  You may place
+ additional permissions on material, added by you to a covered work,
+ for which you have or can give appropriate copyright permission.
+ .
+ Notwithstanding any other provision of this License, for material you
+ add to a covered work, you may (if authorized by the copyright holders of
+ that material) supplement the terms of this License with terms:
+ .
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+ .
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+ .
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+ .
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+ .
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+ .
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+ .
+ All other non-permissive additional terms are considered "further
+ restrictions" within the meaning of section 10.  If the Program as you
+ received it, or any part of it, contains a notice stating that it is
+ governed by this License along with a term that is a further
+ restriction, you may remove that term.  If a license document contains
+ a further restriction but permits relicensing or conveying under this
+ License, you may add to a covered work material governed by the terms
+ of that license document, provided that the further restriction does
+ not survive such relicensing or conveying.
+ .
+ If you add terms to a covered work in accord with this section, you
+ must place, in the relevant source files, a statement of the
+ additional terms that apply to those files, or a notice indicating
+ where to find the applicable terms.
+ .
+ Additional terms, permissive or non-permissive, may be stated in the
+ form of a separately written license, or stated as exceptions;
+ the above requirements apply either way.
+ .
+ 8. Termination.
+ .
+ You may not propagate or modify a covered work except as expressly
+ provided under this License.  Any attempt otherwise to propagate or
+ modify it is void, and will automatically terminate your rights under
+ this License (including any patent licenses granted under the third
+ paragraph of section 11).
+ .
+ However, if you cease all violation of this License, then your
+ license from a particular copyright holder is reinstated (a)
+ provisionally, unless and until the copyright holder explicitly and
+ finally terminates your license, and (b) permanently, if the copyright
+ holder fails to notify you of the violation by some reasonable means
+ prior to 60 days after the cessation.
+ .
+ Moreover, your license from a particular copyright holder is
+ reinstated permanently if the copyright holder notifies you of the
+ violation by some reasonable means, this is the first time you have
+ received notice of violation of this License (for any work) from that
+ copyright holder, and you cure the violation prior to 30 days after
+ your receipt of the notice.
+ .
+ Termination of your rights under this section does not terminate the
+ licenses of parties who have received copies or rights from you under
+ this License.  If your rights have been terminated and not permanently
+ reinstated, you do not qualify to receive new licenses for the same
+ material under section 10.
+ .
+ 9. Acceptance Not Required for Having Copies.
+ .
+ You are not required to accept this License in order to receive or
+ run a copy of the Program.  Ancillary propagation of a covered work
+ occurring solely as a consequence of using peer-to-peer transmission
+ to receive a copy likewise does not require acceptance.  However,
+ nothing other than this License grants you permission to propagate or
+ modify any covered work.  These actions infringe copyright if you do
+ not accept this License.  Therefore, by modifying or propagating a
+ covered work, you indicate your acceptance of this License to do so.
+ .
+ 10. Automatic Licensing of Downstream Recipients.
+ .
+ Each time you convey a covered work, the recipient automatically
+ receives a license from the original licensors, to run, modify and
+ propagate that work, subject to this License.  You are not responsible
+ for enforcing compliance by third parties with this License.
+ .
+ An "entity transaction" is a transaction transferring control of an
+ organization, or substantially all assets of one, or subdividing an
+ organization, or merging organizations.  If propagation of a covered
+ work results from an entity transaction, each party to that
+ transaction who receives a copy of the work also receives whatever
+ licenses to the work the party's predecessor in interest had or could
+ give under the previous paragraph, plus a right to possession of the
+ Corresponding Source of the work from the predecessor in interest, if
+ the predecessor has it or can get it with reasonable efforts.
+ .
+ You may not impose any further restrictions on the exercise of the
+ rights granted or affirmed under this License.  For example, you may
+ not impose a license fee, royalty, or other charge for exercise of
+ rights granted under this License, and you may not initiate litigation
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ any patent claim is infringed by making, using, selling, offering for
+ sale, or importing the Program or any portion of it.
+ .
+ 11. Patents.
+ .
+ A "contributor" is a copyright holder who authorizes use under this
+ License of the Program or a work on which the Program is based.  The
+ work thus licensed is called the contributor's "contributor version".
+ .
+ A contributor's "essential patent claims" are all patent claims
+ owned or controlled by the contributor, whether already acquired or
+ hereafter acquired, that would be infringed by some manner, permitted
+ by this License, of making, using, or selling its contributor version,
+ but do not include claims that would be infringed only as a
+ consequence of further modification of the contributor version.  For
+ purposes of this definition, "control" includes the right to grant
+ patent sublicenses in a manner consistent with the requirements of
+ this License.
+ .
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+ patent license under the contributor's essential patent claims, to
+ make, use, sell, offer for sale, import and otherwise run, modify and
+ propagate the contents of its contributor version.
+ .
+ In the following three paragraphs, a "patent license" is any express
+ agreement or commitment, however denominated, not to enforce a patent
+ (such as an express permission to practice a patent or covenant not to
+ sue for patent infringement).  To "grant" such a patent license to a
+ party means to make such an agreement or commitment not to enforce a
+ patent against the party.
+ .
+ If you convey a covered work, knowingly relying on a patent license,
+ and the Corresponding Source of the work is not available for anyone
+ to copy, free of charge and under the terms of this License, through a
+ publicly available network server or other readily accessible means,
+ then you must either (1) cause the Corresponding Source to be so
+ available, or (2) arrange to deprive yourself of the benefit of the
+ patent license for this particular work, or (3) arrange, in a manner
+ consistent with the requirements of this License, to extend the patent
+ license to downstream recipients.  "Knowingly relying" means you have
+ actual knowledge that, but for the patent license, your conveying the
+ covered work in a country, or your recipient's use of the covered work
+ in a country, would infringe one or more identifiable patents in that
+ country that you have reason to believe are valid.
+ .
+ If, pursuant to or in connection with a single transaction or
+ arrangement, you convey, or propagate by procuring conveyance of, a
+ covered work, and grant a patent license to some of the parties
+ receiving the covered work authorizing them to use, propagate, modify
+ or convey a specific copy of the covered work, then the patent license
+ you grant is automatically extended to all recipients of the covered
+ work and works based on it.
+ .
+ A patent license is "discriminatory" if it does not include within
+ the scope of its coverage, prohibits the exercise of, or is
+ conditioned on the non-exercise of one or more of the rights that are
+ specifically granted under this License.  You may not convey a covered
+ work if you are a party to an arrangement with a third party that is
+ in the business of distributing software, under which you make payment
+ to the third party based on the extent of your activity of conveying
+ the work, and under which the third party grants, to any of the
+ parties who would receive the covered work from you, a discriminatory
+ patent license (a) in connection with copies of the covered work
+ conveyed by you (or copies made from those copies), or (b) primarily
+ for and in connection with specific products or compilations that
+ contain the covered work, unless you entered into that arrangement,
+ or that patent license was granted, prior to 28 March 2007.
+ .
+ Nothing in this License shall be construed as excluding or limiting
+ any implied license or other defenses to infringement that may
+ otherwise be available to you under applicable patent law.
+ .
+ 12. No Surrender of Others' Freedom.
+ .
+ If conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License.  If you cannot convey a
+ covered work so as to satisfy simultaneously your obligations under this
+ License and any other pertinent obligations, then as a consequence you may
+ not convey it at all.  For example, if you agree to terms that obligate you
+ to collect a royalty for further conveying from those to whom you convey
+ the Program, the only way you could satisfy both those terms and this
+ License would be to refrain entirely from conveying the Program.
+ .
+ 13. Remote Network Interaction; Use with the GNU General Public License.
+ .
+ Notwithstanding any other provision of this License, if you modify the
+ Program, your modified version must prominently offer all users
+ interacting with it remotely through a computer network (if your version
+ supports such interaction) an opportunity to receive the Corresponding
+ Source of your version by providing access to the Corresponding Source
+ from a network server at no charge, through some standard or customary
+ means of facilitating copying of software.  This Corresponding Source
+ shall include the Corresponding Source for any work covered by version 3
+ of the GNU General Public License that is incorporated pursuant to the
+ following paragraph.
+ .
+ Notwithstanding any other provision of this License, you have
+ permission to link or combine any covered work with a work licensed
+ under version 3 of the GNU General Public License into a single
+ combined work, and to convey the resulting work.  The terms of this
+ License will continue to apply to the part which is the covered work,
+ but the work with which it is combined will remain governed by version
+ 3 of the GNU General Public License.
+ .
+ 14. Revised Versions of this License.
+ .
+ The Free Software Foundation may publish revised and/or new versions of
+ the GNU Affero General Public License from time to time.  Such new versions
+ will be similar in spirit to the present version, but may differ in detail to
+ address new problems or concerns.
+ .
+ Each version is given a distinguishing version number.  If the
+ Program specifies that a certain numbered version of the GNU Affero General
+ Public License "or any later version" applies to it, you have the
+ option of following the terms and conditions either of that numbered
+ version or of any later version published by the Free Software
+ Foundation.  If the Program does not specify a version number of the
+ GNU Affero General Public License, you may choose any version ever published
+ by the Free Software Foundation.
+ .
+ If the Program specifies that a proxy can decide which future
+ versions of the GNU Affero General Public License can be used, that proxy's
+ public statement of acceptance of a version permanently authorizes you
+ to choose that version for the Program.
+ .
+ Later license versions may give you additional or different
+ permissions.  However, no additional obligations are imposed on any
+ author or copyright holder as a result of your choosing to follow a
+ later version.
+ .
+ 15. Disclaimer of Warranty.
+ .
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+ APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+ IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+ .
+ 16. Limitation of Liability.
+ .
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+ USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGES.
+ .
+ 17. Interpretation of Sections 15 and 16.
+ .
+ If the disclaimer of warranty and limitation of liability provided
+ above cannot be given local legal effect according to their terms,
+ reviewing courts shall apply local law that most closely approximates
+ an absolute waiver of all civil liability in connection with the
+ Program, unless a warranty or assumption of liability accompanies a
+ copy of the Program in return for a fee.
diff --git a/debian/docs b/debian/docs
new file mode 100644 (file)
index 0000000..2fcf0ac
--- /dev/null
@@ -0,0 +1,9 @@
+readme-mac.txt
+readme-mac.txt
+README.md
+readme-perl.txt
+readme-perl.txt
+readme-python.txt
+readme-python.txt
+readme.txt
+readme.txt
diff --git a/debian/files b/debian/files
new file mode 100644 (file)
index 0000000..4595ee6
--- /dev/null
@@ -0,0 +1 @@
+clewarecontrol_4.3-1_amd64.deb devel optional
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..79fd842
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+%:
+       dh $@ 
diff --git a/debian/source/format b/debian/source/format
new file mode 100644 (file)
index 0000000..163aaf8
--- /dev/null
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/error.cpp b/error.cpp
new file mode 100644 (file)
index 0000000..e8cf4af
--- /dev/null
+++ b/error.cpp
@@ -0,0 +1,21 @@
+// SVN: $Revision: 56 $
+#include <errno.h>
+#include <stdarg.h>
+#include <string.h>
+#include <vector>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+void error_exit(const char *format, ...)
+{
+       va_list ap;
+
+       va_start(ap, format);
+       vfprintf(stderr, format, ap);
+       va_end(ap);
+
+       fprintf(stderr, "\nerrno at that time: %s (%d)\n", strerror(errno), errno);
+
+       exit(EXIT_FAILURE);
+}
diff --git a/error.h b/error.h
new file mode 100644 (file)
index 0000000..0811fb9
--- /dev/null
+++ b/error.h
@@ -0,0 +1,2 @@
+// SVN: $Revision: 56 $
+void error_exit(const char *format, ...);
diff --git a/example.pl b/example.pl
new file mode 100755 (executable)
index 0000000..44e669f
--- /dev/null
@@ -0,0 +1,254 @@
+#! /usr/bin/perl -w
+
+use cleware;
+use Data::Dumper;
+
+sub device_id_to_string
+{
+       my $device_type = $_[0];
+
+        if ($device_type eq $cleware::POWER_DEVICE)
+       {
+                return "Power";
+       }
+        if ($device_type eq $cleware::WATCHDOGXP_DEVICE)
+       {
+                return "WatchdogXP";
+       }
+        if ($device_type eq $cleware::LED_DEVICE)
+       {
+                return "LED";
+       }
+        if ($device_type eq $cleware::WATCHDOG_DEVICE)
+       {
+                return "Watchdog";
+       }
+        if ($device_type eq $cleware::AUTORESET_DEVICE)
+       {
+                return "Autoreset device";
+       }
+        if ($device_type eq $cleware::SWITCH1_DEVICE)
+       {
+                return "Switch1";
+       }
+        if ($device_type eq $cleware::SWITCH2_DEVICE)
+       {
+                return "Switch2";
+       }
+        if ($device_type eq $cleware::SWITCH3_DEVICE)
+       {
+                return "Switch3";
+       }
+        if ($device_type eq $cleware::SWITCH4_DEVICE)
+       {
+                return "Switch4";
+       }
+        if ($device_type eq $cleware::SWITCH5_DEVICE)
+       {
+                return "Switch5";
+       }
+        if ($device_type eq $cleware::SWITCH6_DEVICE)
+       {
+                return "Switch6";
+       }
+        if ($device_type eq $cleware::SWITCH7_DEVICE)
+       {
+                return "Switch7";
+       }
+        if ($device_type eq $cleware::SWITCH8_DEVICE)
+       {
+                return "Switch8";
+       }
+        if ($device_type eq $cleware::SWITCHX_DEVICE)
+       {
+                return "SwitchX";
+       }
+        if ($device_type eq $cleware::TEMPERATURE_DEVICE)
+       {
+                return "Temperature sensor";
+       }
+        if ($device_type eq $cleware::TEMPERATURE2_DEVICE)
+       {
+                return "Temperature 2 sensor";
+       }
+        if ($device_type eq $cleware::TEMPERATURE5_DEVICE)
+       {
+                return "Temperature 5 sensor";
+       }
+        if ($device_type eq $cleware::HUMIDITY1_DEVICE)
+       {
+                return "Humidity sensor";
+       }
+        if ($device_type eq $cleware::CONTACT00_DEVICE)
+       {
+                return "Contact 00 device";
+       }
+        if ($device_type eq $cleware::CONTACT01_DEVICE)
+       {
+                return "Contact 01 device";
+       }
+        if ($device_type eq $cleware::CONTACT02_DEVICE)
+       {
+                return "Contact 02 device";
+       }
+        if ($device_type eq $cleware::CONTACT03_DEVICE)
+       {
+                return "Contact 03 device";
+       }
+        if ($device_type eq $cleware::CONTACT04_DEVICE)
+       {
+                return "Contact 04 device";
+       }
+        if ($device_type eq $cleware::CONTACT05_DEVICE)
+       {
+                return "Contact 05 device";
+       }
+        if ($device_type eq $cleware::CONTACT06_DEVICE)
+       {
+                return "Contact 06 device";
+       }
+        if ($device_type eq $cleware::CONTACT07_DEVICE)
+       {
+                return "Contact 07 device";
+       }
+        if ($device_type eq $cleware::CONTACT08_DEVICE)
+       {
+                return "Contact 08 device";
+       }
+        if ($device_type eq $cleware::CONTACT09_DEVICE)
+       {
+                return "Contact 09 device";
+       }
+        if ($device_type eq $cleware::CONTACT10_DEVICE)
+       {
+                return "Contact 10 device";
+       }
+        if ($device_type eq $cleware::CONTACT11_DEVICE)
+       {
+                return "Contact 11 device";
+       }
+        if ($device_type eq $cleware::CONTACT12_DEVICE)
+       {
+                return "Contact 12 device";
+       }
+        if ($device_type eq $cleware::CONTACT13_DEVICE)
+       {
+                return "Contact 13 device";
+       }
+        if ($device_type eq $cleware::CONTACT14_DEVICE)
+       {
+                return "Contact 14 device";
+       }
+        if ($device_type eq $cleware::CONTACT15_DEVICE)
+       {
+                return "Contact 15 device";
+       }
+        if ($device_type eq $cleware::ENCODER01_DEVICE)
+       {
+                return "Encoder 01 device";
+       }
+        if ($device_type eq $cleware::F4_DEVICE)
+       {
+                return "F4 device";
+       }
+        if ($device_type eq $cleware::KEYC01_DEVICE)
+       {
+                return "Keyc01 device";
+       }
+        if ($device_type eq $cleware::KEYC16_DEVICE)
+       {
+                return "Keyc16 device";
+       }
+        if ($device_type eq $cleware::ADC0800_DEVICE)
+       {
+                return "AC0800 device";
+       }
+        if ($device_type eq $cleware::ADC0801_DEVICE)
+       {
+                return "AC0801 device";
+       }
+        if ($device_type eq $cleware::ADC0802_DEVICE)
+       {
+                return "AC0802 device";
+       }
+        if ($device_type eq $cleware::ADC0803_DEVICE)
+       {
+                return "AC0803 device";
+       }
+        if ($device_type eq $cleware::COUNTER00_DEVICE)
+       {
+                return "Counter device";
+       }
+        if ($device_type eq $cleware::BUTTON_NODEVICE)
+       {
+                return "Button no device";
+       }
+
+       return "device type not recognized!"
+}
+
+$c = cleware::CUSBaccess->new();
+
+$n_devices = cleware::CUSBaccess::OpenCleware($c);
+
+print "Number of devices: $n_devices\n";
+
+my $i;
+for($i=0; $i<$n_devices; $i++)
+{
+        my $devType = cleware::CUSBaccess::GetUSBType($c, $i);
+        my $devTypeStr = device_id_to_string($devType);
+        my $version = cleware::CUSBaccess::GetVersion($c, $i);
+        my $serial = cleware::CUSBaccess::GetSerialNumber($c, $i);
+
+        print "device: $i, type: $devTypeStr ($devType), version: $version, serial number: $serial\n";
+
+        # these two are not neccessary normally for reading temperatures
+        # they're here as an example
+        # rc is 0 for failure, 1 for ok
+       my $rc;
+        $rc = cleware::CUSBaccess::ResetDevice($c, $i);
+        $rc = cleware::CUSBaccess::StartDevice($c, $i);
+
+       if ($devType eq $cleware::TEMPERATURE_DEVICE || $devType eq $cleware::TEMPERATURE2_DEVICE || $devType eq $cleware::TEMPERATURE5_DEVICE)
+       {
+               my $temperature = cleware::CUSBaccess::GetTemperatureSimple($c, $i);
+
+               print "\tcurrent temperature: $temperature\n";
+       }
+
+       if ($devType eq $cleware::HUMIDITY1_DEVICE)
+       {
+               my $humidity = cleware::CUSBaccess::GetHumiditySimple($c, $i);
+
+               print "\tcurrent humidity: $humidity\n";
+       }
+
+       # Note: the "ampel" (traffic light) is also a switch device, with actually 3 switches (one per light)
+       if ($devType eq $cleware::SWITCH1_DEVICE || $devType eq $cleware::SWITCH2_DEVICE || $devType eq $cleware::SWITCH3_DEVICE || $devType eq $cleware::SWITCH4_DEVICE || $devType eq $cleware::SWITCH5_DEVICE || $devType eq $cleware::SWITCH6_DEVICE || $devType eq $cleware::SWITCH7_DEVICE || $devType eq $cleware::SWITCH8_DEVICE || $devType eq $cleware::SWITCHX_DEVICE)
+       {
+               my $switch_nr = 0; # 0...15
+               my $state = cleware::CUSBaccess::GetSwitch($c, $i, 16 + $switch_nr);
+               print "\tswitch $switch_nr state: $state\n";
+
+               my $new_state = 1; # 0 or 1
+               $rc = cleware::CUSBaccess::SetSwitch($c, $i, 16 + $switch_nr, $new_state);
+       }
+
+       if ($devType eq $cleware::CUSBaccess::LED_DEVICE)
+       {
+               my $led = $cleware::CUSBaccess::LED_0; # 0...3
+               my $value = 10; # 0...15
+               $rc = cleware::CUSBaccess::SetLED($c, $i, $led, $value);
+       }
+
+       if ($devType eq $cleware::ADC0800_DEVICE || $devType eq $cleware::ADC0801_DEVICE || $devType eq $cleware::ADC0802_DEVICE || $devType eq $cleware::ADC0803_DEVICE)
+       {
+               my $channel = 1; # 0 or 1
+               $rc = cleware::CUSBaccess::SelectADCChannel($c, $i, $channel);
+
+               my $scale = 0; # 0...2 for 5, 13 or 24V
+               my $voltage = cleware::CUSBaccess::GetADCValue($c, $i, $scale);
+               print "\tmeasured voltage: $voltage\n";
+       }
+}
diff --git a/example.py b/example.py
new file mode 100755 (executable)
index 0000000..7329f07
--- /dev/null
@@ -0,0 +1,149 @@
+#! /usr/bin/python
+
+import cleware
+
+def device_id_to_string(device_type):
+        if device_type == cleware.POWER_DEVICE:
+                return "Power"
+        if device_type == cleware.WATCHDOGXP_DEVICE:
+                return "WatchdogXP"
+        if device_type == cleware.LED_DEVICE:
+                return "LED"
+        if device_type == cleware.WATCHDOG_DEVICE:
+                return "Watchdog"
+        if device_type == cleware.AUTORESET_DEVICE:
+                return "Autoreset device"
+        if device_type == cleware.SWITCH1_DEVICE:
+                return "Switch1"
+        if device_type == cleware.SWITCH2_DEVICE:
+                return "Switch2"
+        if device_type == cleware.SWITCH3_DEVICE:
+                return "Switch3"
+        if device_type == cleware.SWITCH4_DEVICE:
+                return "Switch4"
+        if device_type == cleware.SWITCH5_DEVICE:
+                return "Switch5"
+        if device_type == cleware.SWITCH6_DEVICE:
+                return "Switch6"
+        if device_type == cleware.SWITCH7_DEVICE:
+                return "Switch7"
+        if device_type == cleware.SWITCH8_DEVICE:
+                return "Switch8"
+        if device_type == cleware.SWITCHX_DEVICE:
+                return "SwitchX"
+        if device_type == cleware.TEMPERATURE_DEVICE:
+                return "Temperature sensor"
+        if device_type == cleware.TEMPERATURE2_DEVICE:
+                return "Temperature 2 sensor"
+        if device_type == cleware.TEMPERATURE5_DEVICE:
+                return "Temperature 5 sensor"
+        if device_type == cleware.HUMIDITY1_DEVICE:
+                return "Humidity sensor"
+        if device_type == cleware.CONTACT00_DEVICE:
+                return "Contact 00 device"
+        if device_type == cleware.CONTACT01_DEVICE:
+                return "Contact 01 device"
+        if device_type == cleware.CONTACT02_DEVICE:
+                return "Contact 02 device"
+        if device_type == cleware.CONTACT03_DEVICE:
+                return "Contact 03 device"
+        if device_type == cleware.CONTACT04_DEVICE:
+                return "Contact 04 device"
+        if device_type == cleware.CONTACT05_DEVICE:
+                return "Contact 05 device"
+        if device_type == cleware.CONTACT06_DEVICE:
+                return "Contact 06 device"
+        if device_type == cleware.CONTACT07_DEVICE:
+                return "Contact 07 device"
+        if device_type == cleware.CONTACT08_DEVICE:
+                return "Contact 08 device"
+        if device_type == cleware.CONTACT09_DEVICE:
+                return "Contact 09 device"
+        if device_type == cleware.CONTACT10_DEVICE:
+                return "Contact 10 device"
+        if device_type == cleware.CONTACT11_DEVICE:
+                return "Contact 11 device"
+        if device_type == cleware.CONTACT12_DEVICE:
+                return "Contact 12 device"
+        if device_type == cleware.CONTACT13_DEVICE:
+                return "Contact 13 device"
+        if device_type == cleware.CONTACT14_DEVICE:
+                return "Contact 14 device"
+        if device_type == cleware.CONTACT15_DEVICE:
+                return "Contact 15 device"
+        if device_type == cleware.ENCODER01_DEVICE:
+                return "Encoder 01 device"
+        if device_type == cleware.F4_DEVICE:
+                return "F4 device"
+        if device_type == cleware.KEYC01_DEVICE:
+                return "Keyc01 device"
+        if device_type == cleware.KEYC16_DEVICE:
+                return "Keyc16 device"
+        if device_type == cleware.ADC0800_DEVICE:
+                return "AC0800 device"
+        if device_type == cleware.ADC0801_DEVICE:
+                return "AC0801 device"
+        if device_type == cleware.ADC0802_DEVICE:
+                return "AC0802 device"
+        if device_type == cleware.ADC0803_DEVICE:
+                return "AC0803 device"
+        if device_type == cleware.COUNTER00_DEVICE:
+                return "Counter device"
+        if device_type == cleware.BUTTON_NODEVICE:
+                return "Button no device"
+
+       return "device type not recognized!"
+
+
+c = cleware.CUSBaccess()
+
+n_devices = c.OpenCleware()
+
+print "Number of devices: %d" % (n_devices)
+
+for i in range(n_devices):
+       devType = c.GetUSBType(i);
+       devTypeStr = device_id_to_string(devType)
+       version = c.GetVersion(i)
+       serial = c.GetSerialNumber(i)
+
+       print "device: %d, type: %s (%d), version: %d, serial number: %d" % (i, devTypeStr, devType, version, serial)
+
+       # these two are not neccessary normally for reading temperatures
+       # they're here as an example
+       # rc is 0 for failure, 1 for ok
+       rc = c.ResetDevice(i);
+       rc = c.StartDevice(i);
+
+       if devType == cleware.TEMPERATURE_DEVICE or devType == cleware.TEMPERATURE2_DEVICE or devType == cleware.TEMPERATURE5_DEVICE:
+               temperature = c.GetTemperatureSimple(i)
+
+               print "\tcurrent temperature: %f" % (temperature)
+
+       if devType == cleware.HUMIDITY1_DEVICE:
+               humidity = c.GetHumiditySimple(i)
+
+               print "\tcurrent humidity: %f" % (humidity)
+
+       # Note: the "ampel" (traffic light) is also a switch device, with actually 3 switches (one per light)
+       if devType == cleware.SWITCH1_DEVICE or devType == cleware.SWITCH2_DEVICE or devType == cleware.SWITCH3_DEVICE or devType == cleware.SWITCH4_DEVICE or devType == cleware.SWITCH5_DEVICE or devType == cleware.SWITCH6_DEVICE or devType == cleware.SWITCH7_DEVICE or devType == cleware.SWITCH8_DEVICE or devType == cleware.SWITCHX_DEVICE:
+
+               switch_nr = 0 # 0...15
+               state = c.GetSwitch(i, 16 + switch_nr)
+               print "\tswitch %d state: %d" % (switch_nr, state)
+
+               new_state = 1 # 0 or 1
+               rc = c.SetSwitch(i, 16 + switch_nr, new_state)
+
+       if devType == c.LED_DEVICE:
+               led = 1 # 0...3
+               value = 10 # 0...15
+               rc = c.SetLED(i, led, value)
+
+       if devType == c.ADC0800_DEVICE or devType == c.ADC0801_DEVICE or devType == c.ADC0802_DEVICE or devType == c.ADC0803_DEVICE:
+               channel = 1 # 0 or 1
+               rc = c.SelectADCChannel(i, channel)
+
+               scale = 0 # 0...2 for 5, 13 or 24V
+               voltage = c.GetADCValue(i, scale)
+               print "\tmeasured voltage: %f" % (voltage)
diff --git a/examples/Munin/cleware-munin.sh b/examples/Munin/cleware-munin.sh
new file mode 100644 (file)
index 0000000..13caae2
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# written by lars falk-petersen, dev@falk-petersen.no
+
+#clewarecontrol device id (this should be moved to separate config file)
+ID=7778
+
+case $1 in
+   config)
+        cat <<'EOM'
+graph_title Temperature And Humidity
+graph_vlabel C / %
+graph_category sensors
+temp.label Temperature
+hum.label Humidity
+graph_order temp hum
+graph_args --base 1000
+
+EOM
+        exit 0;;
+esac
+
+clewarecontrol -ag > /dev/null 2>&1
+
+echo -n "temp.value "
+clewarecontrol -d $ID -b -rt
+
+echo -n "hum.value "
+clewarecontrol -d $ID -b -rh
+
diff --git a/examples/Nagios/RCS/cleware_nagios_script,v b/examples/Nagios/RCS/cleware_nagios_script,v
new file mode 100755 (executable)
index 0000000..6f3ebee
--- /dev/null
@@ -0,0 +1,40 @@
+head   1.1;
+access;
+symbols;
+locks
+       folkert:1.1; strict;
+comment        @# @;
+
+
+1.1
+date   2010.06.10.19.16.47;    author folkert; state Exp;
+branches;
+next   ;
+
+
+desc
+@@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@#!/bin/sh
+
+MEASURED_TEMPERATURE=`/usr/bin/clewarecontrol -rt 2> /dev/null | grep 'Temperature' | awk '{ print $2; }' | sed -e "s/^\([0-9]*\).*$/\1/g"`
+
+if [ $MEASURED_TEMPERATURE -gt $2 ] ; then
+       echo CRITICAL - temperature above $2 - $MEASURED_TEMPERATURE
+       exit 2
+fi
+
+if [ $MEASURED_TEMPERATURE -gt $1 ] ; then
+       echo WARNING - temperature above $1 - $MEASURED_TEMPERATURE
+       exit 1
+fi
+
+echo OK - temperature is $MEASURED_TEMPERATURE
+exit 0
+@
diff --git a/examples/Nagios/cleware_nagios_script b/examples/Nagios/cleware_nagios_script
new file mode 100755 (executable)
index 0000000..812cce7
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+if [ -z "$1" -o -z "$2" ] ; then
+        echo "CRITICAL - Parameter(s) missing (Warning Critical)."
+        exit 2
+fi
+
+PARAM1=`echo $1 | tr -c -d [:digit:]`
+PARAM2=`echo $2 | tr -c -d [:digit:]`
+
+if [ "$1" != "$PARAM1" -o "$2" != "$PARAM2" ] ; then
+        echo "CRITICAL - invalid parameter(s), only integers allowed."
+        exit 2
+fi
+
+MEASURED_TEMPERATURE=`/usr/bin/clewarecontrol -rt 2> /dev/null | grep 'Temperature' | awk '{ print $2; }'`
+
+NAGIOS_TEMPERATURE=`echo $MEASURED_TEMPERATURE  | sed -e "s/^\([0-9]*\).*$/\1/g"`
+if [ -z "$NAGIOS_TEMPERATURE" ] ; then
+        echo CRITICAL - invalid temperature $MEASURED_TEMPERATURE
+        exit 2
+fi
+if [ $NAGIOS_TEMPERATURE -gt $2 ] ; then
+        echo CRITICAL - temperature above $2 - $MEASURED_TEMPERATURE
+        exit 2
+fi
+
+if [ $NAGIOS_TEMPERATURE -gt $1 ] ; then
+        echo WARNING - temperature above $1 - $MEASURED_TEMPERATURE
+        exit 1
+fi
+
+echo OK - temperature is $MEASURED_TEMPERATURE
+exit 0
diff --git a/examples/Nagios/nagios.txt b/examples/Nagios/nagios.txt
new file mode 100644 (file)
index 0000000..8f8dfe5
--- /dev/null
@@ -0,0 +1,42 @@
+Monitoring temperature with Nagios
+----------------------------------
+
+Files:
+ - nagios.txt
+ - cleware_nagios_script
+
+1. copy cleware_nagios_script to the libexec directory of nagios
+
+2. add the following to the nagios configuration file
+   (checkcommands.cfg):
+
+   define command{
+          command_name    check_cleware_temperature
+          command_line    $USER1$/cleware_nagios_script $ARG1$ $ARG2$
+   }
+
+3. now define a check:
+
+   define service {
+        use                             generic-service
+        is_volatile                     0
+        check_period                    24x7
+        max_check_attempts              3
+        normal_check_interval           5
+        retry_check_interval            1
+        contact_groups                  CONTACTGROUP
+        notification_interval           240
+        notification_period             24x7
+        notification_options            c,r
+        host_name                       HOSTNAME
+        service_description             check temperature using Cleware sensor
+        check_command                   check_cleware_temperature!WARN!CRIT
+        }
+
+4. of course you need to replace 'CONTACTGROUP' and 'HOSTNAME' with
+   the appropriate settings. also 'WARN' and 'CRIT' must be
+   replaced with the warning and critical temperatures
+
+
+For any question related to Cleware devices under Linux, feel free to
+contact me at the following e-mail address: folkert@vanheusden.com
diff --git a/examples/Nagios/seealso.txt b/examples/Nagios/seealso.txt
new file mode 100644 (file)
index 0000000..ad67ec7
--- /dev/null
@@ -0,0 +1,4 @@
+Please also check:
+http://www.vanheusden.com/nagamp/
+
+That tool shows the current Nagios status using the Cleware 'ample' (trafficlight) device.
diff --git a/examples/RRD/add_measurement_to_rrd b/examples/RRD/add_measurement_to_rrd
new file mode 100755 (executable)
index 0000000..c261043
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+MEASURED_TEMPERATURE=`clewarecontrol -rt 2> /dev/null | grep 'Temperature' | awk '{ print $2; }'`
+
+rrdtool update cleware_data.rrd N:$MEASURED_TEMPERATURE
diff --git a/examples/RRD/draw_graph_from_rrd b/examples/RRD/draw_graph_from_rrd
new file mode 100755 (executable)
index 0000000..64cba57
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+rrdtool graph graph.png -a PNG \
+       DEF:temp=cleware_data.rrd:temperature:AVERAGE \
+       LINE1:temp#FF0000:"temperatures"
diff --git a/examples/RRD/make_rrd b/examples/RRD/make_rrd
new file mode 100755 (executable)
index 0000000..ef244c3
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+rrdtool create cleware_data.rrd DS:temperature:GAUGE:300:U:U RRA:AVERAGE:0:1:105192
diff --git a/examples/RRD/rrd.txt b/examples/RRD/rrd.txt
new file mode 100644 (file)
index 0000000..5e30e31
--- /dev/null
@@ -0,0 +1,34 @@
+Creating temperature graphs
+---------------------------
+
+Files:
+ - rrd.txt
+ - make_rrdr
+ - add_measurement_to_rrd
+ - draw_graph_from_rrd
+
+1. First one executes the 'make_rrd' script (ONCE!) to initialize the
+   database in which measurements are stored.
+
+2. Then, from cron for example one executes every 5 minutes the
+   'add_measurement_to_rrd' script. Make sure 'clewarecontrol' is in
+   the path.
+
+3. Every time you would like to have the graphs updated (e.g. you want
+   to see what was measured), invoke the draw_graph_from_rrd script.
+
+4. After invoking the draw-script, you'll find a 'graph.png'-file in
+   the current directory which can be viewed with your favorite
+   picture viewer.
+
+
+These scripts can be easily adapted to measure humidity as well. This
+is left to an excercise for the reader.
+One hint for the humidity sensor: when the power went off of the
+humidity sensor one needs to start it first before the sensor will
+start measuring. Use 'clewarecontrol -ag' for that.
+
+
+
+For any question related to Cleware devices under Linux, feel free to
+contact me at the following e-mail address: folkert@vanheusden.com
diff --git a/examples/Watchdog/clewarewatchdog b/examples/Watchdog/clewarewatchdog
new file mode 100755 (executable)
index 0000000..c7bc3b4
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# Startup script for program
+#
+# chkconfig: 12345 1 1          - This statement tells the chkconfig command how to add or delete this process to the boot process
+# description: Starts the process which pads the Cleware watchdog.
+# processname: clewarecontrol
+
+# Source function library.      This creates the operating environment for the process to be started
+. /etc/rc.d/init.d/functions
+
+case "$1" in
+  start)
+        echo -n "Starting Cleware watchdog "
+        /usr/bin/clewarecontrol -w
+        echo
+        touch /var/lock/subsys/clewarecontrol
+        ;;
+  stop)
+        echo -n "Shutting down Cleware watchdog: "
+        killproc clewarecontrol
+        echo
+        rm -f /var/lock/subsys/clewarecontrol
+        ;;
+  restart)
+        $0 stop
+        $0 start
+        ;;
+  *)
+        echo "Usage: $0 {start|stop|restart}"
+        exit 1
+esac
+
+exit 0
diff --git a/examples/Watchdog/watchdog.txt b/examples/Watchdog/watchdog.txt
new file mode 100644 (file)
index 0000000..f33d560
--- /dev/null
@@ -0,0 +1,19 @@
+Watchdog
+--------
+
+files:
+ - watchdog.txt
+ - clewarewatchdog
+
+1. copy clewarewatchdog to /etc/init.d
+
+2. enable the watchdog:
+   RedHat/SuSE:   chkconfig --level 12345 clewarewatchdog on
+   Debian/Ubuntu: update-rc.d clewarewatchdog start 1 1 2 3 4 5 . stop 99 1 2 3 4 5 .
+
+3. physically install the watchdog, of course one needs
+   to reboot the computer to accomplish this
+
+
+For any question related to Cleware devices under Linux, feel free to
+contact me at the following e-mail address: folkert@vanheusden.com
diff --git a/examples/ampel/ampel.txt b/examples/ampel/ampel.txt
new file mode 100644 (file)
index 0000000..ea89f33
--- /dev/null
@@ -0,0 +1,18 @@
+Blinkin' lights
+---------------
+
+Files:
+ - ampel.txt
+ - script.sh
+
+1. Run 'script.sh':
+   either:
+       ./script.sh
+   or:
+       sh script.sh
+
+4. Enjoy the lights!
+
+
+For any question related to Cleware devices under Linux, feel free to
+contact me at the following e-mail address: folkert@vanheusden.com
diff --git a/examples/ampel/script.sh b/examples/ampel/script.sh
new file mode 100755 (executable)
index 0000000..ffa12e6
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+while [ 1 ]
+do
+        clewarecontrol -as `perl -e 'print rand(3); '` `perl -e 'print rand(2); '`
+done
diff --git a/install-lib.pl b/install-lib.pl
new file mode 100755 (executable)
index 0000000..650ae9f
--- /dev/null
@@ -0,0 +1,19 @@
+#! /usr/bin/perl -w
+
+use File::Copy;
+use File::Path qw(make_path);
+
+foreach(@INC)
+{
+       if (/\/local\//)
+       {
+               print "Installing in $_...\n";
+
+               make_path($_);
+
+               copy('cleware.pm', $_);
+               copy('cleware.so', $_);
+
+               last;
+       }
+}
diff --git a/install-lib.py b/install-lib.py
new file mode 100755 (executable)
index 0000000..37895c7
--- /dev/null
@@ -0,0 +1,19 @@
+#! /usr/bin/python
+
+import sys
+import shutil
+
+found=0
+for p in sys.path:
+       pos = p.find('/local/', 0)
+       if pos >= 0:
+               found=1
+               print 'Installing into %s' % (p)
+               shutil.copy('_cleware.so', p)
+               shutil.copy('cleware.py', p)
+
+if found == 0:
+       print 'Could not find a location to copy the library into.'
+       print 'You may want to install cleware.py and _cleware.so into the appropriate directory.'
+else:
+       print 'Finished.'
diff --git a/mac-hidapi/hid.c b/mac-hidapi/hid.c
new file mode 100644 (file)
index 0000000..38bb635
--- /dev/null
@@ -0,0 +1,1112 @@
+/*******************************************************
+ HIDAPI - Multi-Platform library for
+ communication with HID devices.
+
+ Alan Ott
+ Signal 11 Software
+
+ 2010-07-03
+
+ Copyright 2010, All Rights Reserved.
+
+ At the discretion of the user of this library,
+ this software may be licensed under the terms of the
+ GNU General Public License v3, a BSD-Style license, or the
+ original HIDAPI license as outlined in the LICENSE.txt,
+ LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
+ files located at the root of the source distribution.
+ These files may also be found in the public source
+ code repository located at:
+        http://github.com/signal11/hidapi .
+********************************************************/
+
+/* See Apple Technical Note TN2187 for details on IOHidManager. */
+
+#include <IOKit/hid/IOHIDManager.h>
+#include <IOKit/hid/IOHIDKeys.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <wchar.h>
+#include <locale.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "hidapi.h"
+
+/* Barrier implementation because Mac OSX doesn't have pthread_barrier.
+   It also doesn't have clock_gettime(). So much for POSIX and SUSv2.
+   This implementation came from Brent Priddy and was posted on
+   StackOverflow. It is used with his permission. */
+typedef int pthread_barrierattr_t;
+typedef struct pthread_barrier {
+    pthread_mutex_t mutex;
+    pthread_cond_t cond;
+    int count;
+    int trip_count;
+} pthread_barrier_t;
+
+static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
+{
+       if(count == 0) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       if(pthread_mutex_init(&barrier->mutex, 0) < 0) {
+               return -1;
+       }
+       if(pthread_cond_init(&barrier->cond, 0) < 0) {
+               pthread_mutex_destroy(&barrier->mutex);
+               return -1;
+       }
+       barrier->trip_count = count;
+       barrier->count = 0;
+
+       return 0;
+}
+
+static int pthread_barrier_destroy(pthread_barrier_t *barrier)
+{
+       pthread_cond_destroy(&barrier->cond);
+       pthread_mutex_destroy(&barrier->mutex);
+       return 0;
+}
+
+static int pthread_barrier_wait(pthread_barrier_t *barrier)
+{
+       pthread_mutex_lock(&barrier->mutex);
+       ++(barrier->count);
+       if(barrier->count >= barrier->trip_count)
+       {
+               barrier->count = 0;
+               pthread_cond_broadcast(&barrier->cond);
+               pthread_mutex_unlock(&barrier->mutex);
+               return 1;
+       }
+       else
+       {
+               pthread_cond_wait(&barrier->cond, &(barrier->mutex));
+               pthread_mutex_unlock(&barrier->mutex);
+               return 0;
+       }
+}
+
+static int return_data(hid_device *dev, unsigned char *data, size_t length);
+
+/* Linked List of input reports received from the device. */
+struct input_report {
+       uint8_t *data;
+       size_t len;
+       struct input_report *next;
+};
+
+struct hid_device_ {
+       IOHIDDeviceRef device_handle;
+       int blocking;
+       int uses_numbered_reports;
+       int disconnected;
+       CFStringRef run_loop_mode;
+       CFRunLoopRef run_loop;
+       CFRunLoopSourceRef source;
+       uint8_t *input_report_buf;
+       CFIndex max_input_report_len;
+       struct input_report *input_reports;
+
+       pthread_t thread;
+       pthread_mutex_t mutex; /* Protects input_reports */
+       pthread_cond_t condition;
+       pthread_barrier_t barrier; /* Ensures correct startup sequence */
+       pthread_barrier_t shutdown_barrier; /* Ensures correct shutdown sequence */
+       int shutdown_thread;
+};
+
+static hid_device *new_hid_device(void)
+{
+       hid_device *dev = calloc(1, sizeof(hid_device));
+       dev->device_handle = NULL;
+       dev->blocking = 1;
+       dev->uses_numbered_reports = 0;
+       dev->disconnected = 0;
+       dev->run_loop_mode = NULL;
+       dev->run_loop = NULL;
+       dev->source = NULL;
+       dev->input_report_buf = NULL;
+       dev->input_reports = NULL;
+       dev->shutdown_thread = 0;
+
+       /* Thread objects */
+       pthread_mutex_init(&dev->mutex, NULL);
+       pthread_cond_init(&dev->condition, NULL);
+       pthread_barrier_init(&dev->barrier, NULL, 2);
+       pthread_barrier_init(&dev->shutdown_barrier, NULL, 2);
+
+       return dev;
+}
+
+static void free_hid_device(hid_device *dev)
+{
+       if (!dev)
+               return;
+
+       /* Delete any input reports still left over. */
+       struct input_report *rpt = dev->input_reports;
+       while (rpt) {
+               struct input_report *next = rpt->next;
+               free(rpt->data);
+               free(rpt);
+               rpt = next;
+       }
+
+       /* Free the string and the report buffer. The check for NULL
+          is necessary here as CFRelease() doesn't handle NULL like
+          free() and others do. */
+       if (dev->run_loop_mode)
+               CFRelease(dev->run_loop_mode);
+       if (dev->source)
+               CFRelease(dev->source);
+       free(dev->input_report_buf);
+
+       /* Clean up the thread objects */
+       pthread_barrier_destroy(&dev->shutdown_barrier);
+       pthread_barrier_destroy(&dev->barrier);
+       pthread_cond_destroy(&dev->condition);
+       pthread_mutex_destroy(&dev->mutex);
+
+       /* Free the structure itself. */
+       free(dev);
+}
+
+static IOHIDManagerRef hid_mgr = 0x0;
+
+
+#if 0
+static void register_error(hid_device *device, const char *op)
+{
+
+}
+#endif
+
+
+static int32_t get_int_property(IOHIDDeviceRef device, CFStringRef key)
+{
+       CFTypeRef ref;
+       int32_t value;
+
+       ref = IOHIDDeviceGetProperty(device, key);
+       if (ref) {
+               if (CFGetTypeID(ref) == CFNumberGetTypeID()) {
+                       CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, &value);
+                       return value;
+               }
+       }
+       return 0;
+}
+
+static unsigned short get_vendor_id(IOHIDDeviceRef device)
+{
+       return get_int_property(device, CFSTR(kIOHIDVendorIDKey));
+}
+
+static unsigned short get_product_id(IOHIDDeviceRef device)
+{
+       return get_int_property(device, CFSTR(kIOHIDProductIDKey));
+}
+
+static int32_t get_location_id(IOHIDDeviceRef device)
+{
+       return get_int_property(device, CFSTR(kIOHIDLocationIDKey));
+}
+
+static int32_t get_max_report_length(IOHIDDeviceRef device)
+{
+       return get_int_property(device, CFSTR(kIOHIDMaxInputReportSizeKey));
+}
+
+static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t *buf, size_t len)
+{
+       CFStringRef str;
+
+       if (!len)
+               return 0;
+
+       str = IOHIDDeviceGetProperty(device, prop);
+
+       buf[0] = 0;
+
+       if (str) {
+               CFIndex str_len = CFStringGetLength(str);
+               CFRange range;
+               CFIndex used_buf_len;
+               CFIndex chars_copied;
+
+               len --;
+
+               range.location = 0;
+               range.length = ((size_t)str_len > len)? len: (size_t)str_len;
+               chars_copied = CFStringGetBytes(str,
+                       range,
+                       kCFStringEncodingUTF32LE,
+                       (char)'?',
+                       FALSE,
+                       (UInt8*)buf,
+                       len * sizeof(wchar_t),
+                       &used_buf_len);
+
+               if (chars_copied == len)
+                       buf[len] = 0; /* len is decremented above */
+               else
+                       buf[chars_copied] = 0;
+
+               return 0;
+       }
+       else
+               return -1;
+
+}
+
+static int get_string_property_utf8(IOHIDDeviceRef device, CFStringRef prop, char *buf, size_t len)
+{
+       CFStringRef str;
+       if (!len)
+               return 0;
+
+       str = IOHIDDeviceGetProperty(device, prop);
+
+       buf[0] = 0;
+
+       if (str) {
+               len--;
+
+               CFIndex str_len = CFStringGetLength(str);
+               CFRange range;
+               range.location = 0;
+               range.length = str_len;
+               CFIndex used_buf_len;
+               CFIndex chars_copied;
+               chars_copied = CFStringGetBytes(str,
+                       range,
+                       kCFStringEncodingUTF8,
+                       (char)'?',
+                       FALSE,
+                       (UInt8*)buf,
+                       len,
+                       &used_buf_len);
+
+               if (used_buf_len == len)
+                       buf[len] = 0; /* len is decremented above */
+               else
+                       buf[used_buf_len] = 0;
+
+               return used_buf_len;
+       }
+       else
+               return 0;
+}
+
+
+static int get_serial_number(IOHIDDeviceRef device, wchar_t *buf, size_t len)
+{
+       return get_string_property(device, CFSTR(kIOHIDSerialNumberKey), buf, len);
+}
+
+static int get_manufacturer_string(IOHIDDeviceRef device, wchar_t *buf, size_t len)
+{
+       return get_string_property(device, CFSTR(kIOHIDManufacturerKey), buf, len);
+}
+
+static int get_product_string(IOHIDDeviceRef device, wchar_t *buf, size_t len)
+{
+       return get_string_property(device, CFSTR(kIOHIDProductKey), buf, len);
+}
+
+
+/* Implementation of wcsdup() for Mac. */
+static wchar_t *dup_wcs(const wchar_t *s)
+{
+       size_t len = wcslen(s);
+       wchar_t *ret = malloc((len+1)*sizeof(wchar_t));
+       wcscpy(ret, s);
+
+       return ret;
+}
+
+
+static int make_path(IOHIDDeviceRef device, char *buf, size_t len)
+{
+       int res;
+       unsigned short vid, pid;
+       char transport[32];
+       int32_t location;
+
+       buf[0] = '\0';
+
+       res = get_string_property_utf8(
+               device, CFSTR(kIOHIDTransportKey),
+               transport, sizeof(transport));
+
+       if (!res)
+               return -1;
+
+       location = get_location_id(device);
+       vid = get_vendor_id(device);
+       pid = get_product_id(device);
+
+       res = snprintf(buf, len, "%s_%04hx_%04hx_%x",
+                       transport, vid, pid, location);
+
+
+       buf[len-1] = '\0';
+       return res+1;
+}
+
+/* Initialize the IOHIDManager. Return 0 for success and -1 for failure. */
+static int init_hid_manager(void)
+{
+       /* Initialize all the HID Manager Objects */
+       hid_mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
+       if (hid_mgr) {
+               IOHIDManagerSetDeviceMatching(hid_mgr, NULL);
+               IOHIDManagerScheduleWithRunLoop(hid_mgr, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
+               return 0;
+       }
+
+       return -1;
+}
+
+/* Initialize the IOHIDManager if necessary. This is the public function, and
+   it is safe to call this function repeatedly. Return 0 for success and -1
+   for failure. */
+int HID_API_EXPORT hid_init(void)
+{
+       if (!hid_mgr) {
+               return init_hid_manager();
+       }
+
+       /* Already initialized. */
+       return 0;
+}
+
+int HID_API_EXPORT hid_exit(void)
+{
+       if (hid_mgr) {
+               /* Close the HID manager. */
+               IOHIDManagerClose(hid_mgr, kIOHIDOptionsTypeNone);
+               CFRelease(hid_mgr);
+               hid_mgr = NULL;
+       }
+
+       return 0;
+}
+
+static void process_pending_events(void) {
+       SInt32 res;
+       do {
+               res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.001, FALSE);
+       } while(res != kCFRunLoopRunFinished && res != kCFRunLoopRunTimedOut);
+}
+
+struct hid_device_info  HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
+{
+       struct hid_device_info *root = NULL; /* return object */
+       struct hid_device_info *cur_dev = NULL;
+       CFIndex num_devices;
+       int i;
+
+       /* Set up the HID Manager if it hasn't been done */
+       if (hid_init() < 0)
+               return NULL;
+
+       /* give the IOHIDManager a chance to update itself */
+       process_pending_events();
+
+       /* Get a list of the Devices */
+       IOHIDManagerSetDeviceMatching(hid_mgr, NULL);
+       CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
+
+       /* Convert the list into a C array so we can iterate easily. */
+       num_devices = CFSetGetCount(device_set);
+       IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
+       CFSetGetValues(device_set, (const void **) device_array);
+
+       /* Iterate over each device, making an entry for it. */
+       for (i = 0; i < num_devices; i++) {
+               unsigned short dev_vid;
+               unsigned short dev_pid;
+               #define BUF_LEN 256
+               wchar_t buf[BUF_LEN];
+               char cbuf[BUF_LEN];
+
+               IOHIDDeviceRef dev = device_array[i];
+
+        if (!dev) {
+            continue;
+        }
+               dev_vid = get_vendor_id(dev);
+               dev_pid = get_product_id(dev);
+
+               /* Check the VID/PID against the arguments */
+               if ((vendor_id == 0x0 || vendor_id == dev_vid) &&
+                   (product_id == 0x0 || product_id == dev_pid)) {
+                       struct hid_device_info *tmp;
+                       size_t len;
+
+                       /* VID/PID match. Create the record. */
+                       tmp = malloc(sizeof(struct hid_device_info));
+                       if (cur_dev) {
+                               cur_dev->next = tmp;
+                       }
+                       else {
+                               root = tmp;
+                       }
+                       cur_dev = tmp;
+
+                       /* Get the Usage Page and Usage for this device. */
+                       cur_dev->usage_page = get_int_property(dev, CFSTR(kIOHIDPrimaryUsagePageKey));
+                       cur_dev->usage = get_int_property(dev, CFSTR(kIOHIDPrimaryUsageKey));
+
+                       /* Fill out the record */
+                       cur_dev->next = NULL;
+                       len = make_path(dev, cbuf, sizeof(cbuf));
+                       cur_dev->path = strdup(cbuf);
+
+                       /* Serial Number */
+                       get_serial_number(dev, buf, BUF_LEN);
+                       cur_dev->serial_number = dup_wcs(buf);
+
+                       /* Manufacturer and Product strings */
+                       get_manufacturer_string(dev, buf, BUF_LEN);
+                       cur_dev->manufacturer_string = dup_wcs(buf);
+                       get_product_string(dev, buf, BUF_LEN);
+                       cur_dev->product_string = dup_wcs(buf);
+
+                       /* VID/PID */
+                       cur_dev->vendor_id = dev_vid;
+                       cur_dev->product_id = dev_pid;
+
+                       /* Release Number */
+                       cur_dev->release_number = get_int_property(dev, CFSTR(kIOHIDVersionNumberKey));
+
+                       /* Interface Number (Unsupported on Mac)*/
+                       cur_dev->interface_number = -1;
+               }
+       }
+
+       free(device_array);
+       CFRelease(device_set);
+
+       return root;
+}
+
+void  HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
+{
+       /* This function is identical to the Linux version. Platform independent. */
+       struct hid_device_info *d = devs;
+       while (d) {
+               struct hid_device_info *next = d->next;
+               free(d->path);
+               free(d->serial_number);
+               free(d->manufacturer_string);
+               free(d->product_string);
+               free(d);
+               d = next;
+       }
+}
+
+hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
+{
+       /* This function is identical to the Linux version. Platform independent. */
+       struct hid_device_info *devs, *cur_dev;
+       const char *path_to_open = NULL;
+       hid_device * handle = NULL;
+
+       devs = hid_enumerate(vendor_id, product_id);
+       cur_dev = devs;
+       while (cur_dev) {
+               if (cur_dev->vendor_id == vendor_id &&
+                   cur_dev->product_id == product_id) {
+                       if (serial_number) {
+                               if (wcscmp(serial_number, cur_dev->serial_number) == 0) {
+                                       path_to_open = cur_dev->path;
+                                       break;
+                               }
+                       }
+                       else {
+                               path_to_open = cur_dev->path;
+                               break;
+                       }
+               }
+               cur_dev = cur_dev->next;
+       }
+
+       if (path_to_open) {
+               /* Open the device */
+               handle = hid_open_path(path_to_open);
+       }
+
+       hid_free_enumeration(devs);
+
+       return handle;
+}
+
+static void hid_device_removal_callback(void *context, IOReturn result,
+                                        void *sender)
+{
+       /* Stop the Run Loop for this device. */
+       hid_device *d = context;
+
+       d->disconnected = 1;
+       CFRunLoopStop(d->run_loop);
+}
+
+/* The Run Loop calls this function for each input report received.
+   This function puts the data into a linked list to be picked up by
+   hid_read(). */
+static void hid_report_callback(void *context, IOReturn result, void *sender,
+                         IOHIDReportType report_type, uint32_t report_id,
+                         uint8_t *report, CFIndex report_length)
+{
+       struct input_report *rpt;
+       hid_device *dev = context;
+
+       /* Make a new Input Report object */
+       rpt = calloc(1, sizeof(struct input_report));
+       rpt->data = calloc(1, report_length);
+       memcpy(rpt->data, report, report_length);
+       rpt->len = report_length;
+       rpt->next = NULL;
+
+       /* Lock this section */
+       pthread_mutex_lock(&dev->mutex);
+
+       /* Attach the new report object to the end of the list. */
+       if (dev->input_reports == NULL) {
+               /* The list is empty. Put it at the root. */
+               dev->input_reports = rpt;
+       }
+       else {
+               /* Find the end of the list and attach. */
+               struct input_report *cur = dev->input_reports;
+               int num_queued = 0;
+               while (cur->next != NULL) {
+                       cur = cur->next;
+                       num_queued++;
+               }
+               cur->next = rpt;
+
+               /* Pop one off if we've reached 30 in the queue. This
+                  way we don't grow forever if the user never reads
+                  anything from the device. */
+               if (num_queued > 30) {
+                       return_data(dev, NULL, 0);
+               }
+       }
+
+       /* Signal a waiting thread that there is data. */
+       pthread_cond_signal(&dev->condition);
+
+       /* Unlock */
+       pthread_mutex_unlock(&dev->mutex);
+
+}
+
+/* This gets called when the read_thred's run loop gets signaled by
+   hid_close(), and serves to stop the read_thread's run loop. */
+static void perform_signal_callback(void *context)
+{
+       hid_device *dev = context;
+       CFRunLoopStop(dev->run_loop); /*TODO: CFRunLoopGetCurrent()*/
+}
+
+static void *read_thread(void *param)
+{
+       hid_device *dev = param;
+       SInt32 code;
+
+       /* Move the device's run loop to this thread. */
+       IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode);
+
+       /* Create the RunLoopSource which is used to signal the
+          event loop to stop when hid_close() is called. */
+       CFRunLoopSourceContext ctx;
+       memset(&ctx, 0, sizeof(ctx));
+       ctx.version = 0;
+       ctx.info = dev;
+       ctx.perform = &perform_signal_callback;
+       dev->source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0/*order*/, &ctx);
+       CFRunLoopAddSource(CFRunLoopGetCurrent(), dev->source, dev->run_loop_mode);
+
+       /* Store off the Run Loop so it can be stopped from hid_close()
+          and on device disconnection. */
+       dev->run_loop = CFRunLoopGetCurrent();
+
+       /* Notify the main thread that the read thread is up and running. */
+       pthread_barrier_wait(&dev->barrier);
+
+       /* Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input
+          reports into the hid_report_callback(). */
+       while (!dev->shutdown_thread && !dev->disconnected) {
+               code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE);
+               /* Return if the device has been disconnected */
+               if (code == kCFRunLoopRunFinished) {
+                       dev->disconnected = 1;
+                       break;
+               }
+
+
+               /* Break if The Run Loop returns Finished or Stopped. */
+               if (code != kCFRunLoopRunTimedOut &&
+                   code != kCFRunLoopRunHandledSource) {
+                       /* There was some kind of error. Setting
+                          shutdown seems to make sense, but
+                          there may be something else more appropriate */
+                       dev->shutdown_thread = 1;
+                       break;
+               }
+       }
+
+       /* Now that the read thread is stopping, Wake any threads which are
+          waiting on data (in hid_read_timeout()). Do this under a mutex to
+          make sure that a thread which is about to go to sleep waiting on
+          the condition acutally will go to sleep before the condition is
+          signaled. */
+       pthread_mutex_lock(&dev->mutex);
+       pthread_cond_broadcast(&dev->condition);
+       pthread_mutex_unlock(&dev->mutex);
+
+       /* Wait here until hid_close() is called and makes it past
+          the call to CFRunLoopWakeUp(). This thread still needs to
+          be valid when that function is called on the other thread. */
+       pthread_barrier_wait(&dev->shutdown_barrier);
+
+       return NULL;
+}
+
+hid_device * HID_API_EXPORT hid_open_path(const char *path)
+{
+       int i;
+       hid_device *dev = NULL;
+       CFIndex num_devices;
+
+       dev = new_hid_device();
+
+       /* Set up the HID Manager if it hasn't been done */
+       if (hid_init() < 0)
+               return NULL;
+
+       /* give the IOHIDManager a chance to update itself */
+       process_pending_events();
+
+       CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
+
+       num_devices = CFSetGetCount(device_set);
+       IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
+       CFSetGetValues(device_set, (const void **) device_array);
+       for (i = 0; i < num_devices; i++) {
+               char cbuf[BUF_LEN];
+               size_t len;
+               IOHIDDeviceRef os_dev = device_array[i];
+
+               len = make_path(os_dev, cbuf, sizeof(cbuf));
+               if (!strcmp(cbuf, path)) {
+                       /* Matched Paths. Open this Device. */
+                       IOReturn ret = IOHIDDeviceOpen(os_dev, kIOHIDOptionsTypeSeizeDevice);
+                       if (ret == kIOReturnSuccess) {
+                               char str[32];
+
+                               free(device_array);
+                               CFRetain(os_dev);
+                               CFRelease(device_set);
+                               dev->device_handle = os_dev;
+
+                               /* Create the buffers for receiving data */
+                               dev->max_input_report_len = (CFIndex) get_max_report_length(os_dev);
+                               dev->input_report_buf = calloc(dev->max_input_report_len, sizeof(uint8_t));
+
+                               /* Create the Run Loop Mode for this device.
+                                  printing the reference seems to work. */
+                               sprintf(str, "HIDAPI_%p", os_dev);
+                               dev->run_loop_mode =
+                                       CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII);
+
+                               /* Attach the device to a Run Loop */
+                               IOHIDDeviceRegisterInputReportCallback(
+                                       os_dev, dev->input_report_buf, dev->max_input_report_len,
+                                       &hid_report_callback, dev);
+                               IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev);
+
+                               /* Start the read thread */
+                               pthread_create(&dev->thread, NULL, read_thread, dev);
+
+                               /* Wait here for the read thread to be initialized. */
+                               pthread_barrier_wait(&dev->barrier);
+
+                               return dev;
+                       }
+                       else {
+                               goto return_error;
+                       }
+               }
+       }
+
+return_error:
+       free(device_array);
+       CFRelease(device_set);
+       free_hid_device(dev);
+       return NULL;
+}
+
+static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char *data, size_t length)
+{
+       const unsigned char *data_to_send;
+       size_t length_to_send;
+       IOReturn res;
+
+       /* Return if the device has been disconnected. */
+       if (dev->disconnected)
+               return -1;
+
+       if (data[0] == 0x0) {
+               /* Not using numbered Reports.
+                  Don't send the report number. */
+               data_to_send = data+1;
+               length_to_send = length-1;
+       }
+       else {
+               /* Using numbered Reports.
+                  Send the Report Number */
+               data_to_send = data;
+               length_to_send = length;
+       }
+
+       if (!dev->disconnected) {
+               res = IOHIDDeviceSetReport(dev->device_handle,
+                                          type,
+                                          data[0], /* Report ID*/
+                                          data_to_send, length_to_send);
+
+               if (res == kIOReturnSuccess) {
+                       return length;
+               }
+               else
+                       return -1;
+       }
+
+       return -1;
+}
+
+int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
+{
+       return set_report(dev, kIOHIDReportTypeOutput, data, length);
+}
+
+/* Helper function, so that this isn't duplicated in hid_read(). */
+static int return_data(hid_device *dev, unsigned char *data, size_t length)
+{
+       /* Copy the data out of the linked list item (rpt) into the
+          return buffer (data), and delete the liked list item. */
+       struct input_report *rpt = dev->input_reports;
+       size_t len = (length < rpt->len)? length: rpt->len;
+       memcpy(data, rpt->data, len);
+       dev->input_reports = rpt->next;
+       free(rpt->data);
+       free(rpt);
+       return len;
+}
+
+static int cond_wait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex)
+{
+       while (!dev->input_reports) {
+               int res = pthread_cond_wait(cond, mutex);
+               if (res != 0)
+                       return res;
+
+               /* A res of 0 means we may have been signaled or it may
+                  be a spurious wakeup. Check to see that there's acutally
+                  data in the queue before returning, and if not, go back
+                  to sleep. See the pthread_cond_timedwait() man page for
+                  details. */
+
+               if (dev->shutdown_thread || dev->disconnected)
+                       return -1;
+       }
+
+       return 0;
+}
+
+static int cond_timedwait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
+{
+       while (!dev->input_reports) {
+               int res = pthread_cond_timedwait(cond, mutex, abstime);
+               if (res != 0)
+                       return res;
+
+               /* A res of 0 means we may have been signaled or it may
+                  be a spurious wakeup. Check to see that there's acutally
+                  data in the queue before returning, and if not, go back
+                  to sleep. See the pthread_cond_timedwait() man page for
+                  details. */
+
+               if (dev->shutdown_thread || dev->disconnected)
+                       return -1;
+       }
+
+       return 0;
+
+}
+
+int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
+{
+       int bytes_read = -1;
+
+       /* Lock the access to the report list. */
+       pthread_mutex_lock(&dev->mutex);
+
+       /* There's an input report queued up. Return it. */
+       if (dev->input_reports) {
+               /* Return the first one */
+               bytes_read = return_data(dev, data, length);
+               goto ret;
+       }
+
+       /* Return if the device has been disconnected. */
+       if (dev->disconnected) {
+               bytes_read = -1;
+               goto ret;
+       }
+
+       if (dev->shutdown_thread) {
+               /* This means the device has been closed (or there
+                  has been an error. An error code of -1 should
+                  be returned. */
+               bytes_read = -1;
+               goto ret;
+       }
+
+       /* There is no data. Go to sleep and wait for data. */
+
+       if (milliseconds == -1) {
+               /* Blocking */
+               int res;
+               res = cond_wait(dev, &dev->condition, &dev->mutex);
+               if (res == 0)
+                       bytes_read = return_data(dev, data, length);
+               else {
+                       /* There was an error, or a device disconnection. */
+                       bytes_read = -1;
+               }
+       }
+       else if (milliseconds > 0) {
+               /* Non-blocking, but called with timeout. */
+               int res;
+               struct timespec ts;
+               struct timeval tv;
+               gettimeofday(&tv, NULL);
+               TIMEVAL_TO_TIMESPEC(&tv, &ts);
+               ts.tv_sec += milliseconds / 1000;
+               ts.tv_nsec += (milliseconds % 1000) * 1000000;
+               if (ts.tv_nsec >= 1000000000L) {
+                       ts.tv_sec++;
+                       ts.tv_nsec -= 1000000000L;
+               }
+
+               res = cond_timedwait(dev, &dev->condition, &dev->mutex, &ts);
+               if (res == 0)
+                       bytes_read = return_data(dev, data, length);
+               else if (res == ETIMEDOUT)
+                       bytes_read = 0;
+               else
+                       bytes_read = -1;
+       }
+       else {
+               /* Purely non-blocking */
+               bytes_read = 0;
+       }
+
+ret:
+       /* Unlock */
+       pthread_mutex_unlock(&dev->mutex);
+       return bytes_read;
+}
+
+int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
+{
+       return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0);
+}
+
+int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
+{
+       /* All Nonblocking operation is handled by the library. */
+       dev->blocking = !nonblock;
+
+       return 0;
+}
+
+int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
+{
+       return set_report(dev, kIOHIDReportTypeFeature, data, length);
+}
+
+int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
+{
+       CFIndex len = length;
+       IOReturn res;
+
+       /* Return if the device has been unplugged. */
+       if (dev->disconnected)
+               return -1;
+
+       res = IOHIDDeviceGetReport(dev->device_handle,
+                                  kIOHIDReportTypeFeature,
+                                  data[0], /* Report ID */
+                                  data, &len);
+       if (res == kIOReturnSuccess)
+               return len;
+       else
+               return -1;
+}
+
+
+void HID_API_EXPORT hid_close(hid_device *dev)
+{
+       if (!dev)
+               return;
+
+       /* Disconnect the report callback before close. */
+       if (!dev->disconnected) {
+               IOHIDDeviceRegisterInputReportCallback(
+                       dev->device_handle, dev->input_report_buf, dev->max_input_report_len,
+                       NULL, dev);
+               IOHIDDeviceRegisterRemovalCallback(dev->device_handle, NULL, dev);
+               IOHIDDeviceUnscheduleFromRunLoop(dev->device_handle, dev->run_loop, dev->run_loop_mode);
+               IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
+       }
+
+       /* Cause read_thread() to stop. */
+       dev->shutdown_thread = 1;
+
+       /* Wake up the run thread's event loop so that the thread can exit. */
+       CFRunLoopSourceSignal(dev->source);
+       CFRunLoopWakeUp(dev->run_loop);
+
+       /* Notify the read thread that it can shut down now. */
+       pthread_barrier_wait(&dev->shutdown_barrier);
+
+       /* Wait for read_thread() to end. */
+       pthread_join(dev->thread, NULL);
+
+       /* Close the OS handle to the device, but only if it's not
+          been unplugged. If it's been unplugged, then calling
+          IOHIDDeviceClose() will crash. */
+       if (!dev->disconnected) {
+               IOHIDDeviceClose(dev->device_handle, kIOHIDOptionsTypeSeizeDevice);
+       }
+
+       /* Clear out the queue of received reports. */
+       pthread_mutex_lock(&dev->mutex);
+       while (dev->input_reports) {
+               return_data(dev, NULL, 0);
+       }
+       pthread_mutex_unlock(&dev->mutex);
+       CFRelease(dev->device_handle);
+
+       free_hid_device(dev);
+}
+
+int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
+{
+       return get_manufacturer_string(dev->device_handle, string, maxlen);
+}
+
+int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
+{
+       return get_product_string(dev->device_handle, string, maxlen);
+}
+
+int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
+{
+       return get_serial_number(dev->device_handle, string, maxlen);
+}
+
+int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
+{
+       /* TODO: */
+
+       return 0;
+}
+
+
+HID_API_EXPORT const wchar_t * HID_API_CALL  hid_error(hid_device *dev)
+{
+       /* TODO: */
+
+       return NULL;
+}
+
+
+
+
+
+
+
+#if 0
+static int32_t get_usage(IOHIDDeviceRef device)
+{
+       int32_t res;
+       res = get_int_property(device, CFSTR(kIOHIDDeviceUsageKey));
+       if (!res)
+               res = get_int_property(device, CFSTR(kIOHIDPrimaryUsageKey));
+       return res;
+}
+
+static int32_t get_usage_page(IOHIDDeviceRef device)
+{
+       int32_t res;
+       res = get_int_property(device, CFSTR(kIOHIDDeviceUsagePageKey));
+       if (!res)
+               res = get_int_property(device, CFSTR(kIOHIDPrimaryUsagePageKey));
+       return res;
+}
+
+static int get_transport(IOHIDDeviceRef device, wchar_t *buf, size_t len)
+{
+       return get_string_property(device, CFSTR(kIOHIDTransportKey), buf, len);
+}
+
+
+int main(void)
+{
+       IOHIDManagerRef mgr;
+       int i;
+
+       mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
+       IOHIDManagerSetDeviceMatching(mgr, NULL);
+       IOHIDManagerOpen(mgr, kIOHIDOptionsTypeNone);
+
+       CFSetRef device_set = IOHIDManagerCopyDevices(mgr);
+
+       CFIndex num_devices = CFSetGetCount(device_set);
+       IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
+       CFSetGetValues(device_set, (const void **) device_array);
+
+       for (i = 0; i < num_devices; i++) {
+               IOHIDDeviceRef dev = device_array[i];
+               printf("Device: %p\n", dev);
+               printf("  %04hx %04hx\n", get_vendor_id(dev), get_product_id(dev));
+
+               wchar_t serial[256], buf[256];
+               char cbuf[256];
+               get_serial_number(dev, serial, 256);
+
+
+               printf("  Serial: %ls\n", serial);
+               printf("  Loc: %ld\n", get_location_id(dev));
+               get_transport(dev, buf, 256);
+               printf("  Trans: %ls\n", buf);
+               make_path(dev, cbuf, 256);
+               printf("  Path: %s\n", cbuf);
+
+       }
+
+       return 0;
+}
+#endif
diff --git a/mac-hidapi/hidapi.h b/mac-hidapi/hidapi.h
new file mode 100644 (file)
index 0000000..e5bc2dc
--- /dev/null
@@ -0,0 +1,391 @@
+/*******************************************************
+ HIDAPI - Multi-Platform library for
+ communication with HID devices.
+
+ Alan Ott
+ Signal 11 Software
+
+ 8/22/2009
+
+ Copyright 2009, All Rights Reserved.
+
+ At the discretion of the user of this library,
+ this software may be licensed under the terms of the
+ GNU General Public License v3, a BSD-Style license, or the
+ original HIDAPI license as outlined in the LICENSE.txt,
+ LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
+ files located at the root of the source distribution.
+ These files may also be found in the public source
+ code repository located at:
+        http://github.com/signal11/hidapi .
+********************************************************/
+
+/** @file
+ * @defgroup API hidapi API
+ */
+
+#ifndef HIDAPI_H__
+#define HIDAPI_H__
+
+#include <wchar.h>
+
+#ifdef _WIN32
+      #define HID_API_EXPORT __declspec(dllexport)
+      #define HID_API_CALL
+#else
+      #define HID_API_EXPORT /**< API export macro */
+      #define HID_API_CALL /**< API call macro */
+#endif
+
+#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+               struct hid_device_;
+               typedef struct hid_device_ hid_device; /**< opaque hidapi structure */
+
+               /** hidapi info structure */
+               struct hid_device_info {
+                       /** Platform-specific device path */
+                       char *path;
+                       /** Device Vendor ID */
+                       unsigned short vendor_id;
+                       /** Device Product ID */
+                       unsigned short product_id;
+                       /** Serial Number */
+                       wchar_t *serial_number;
+                       /** Device Release Number in binary-coded decimal,
+                           also known as Device Version Number */
+                       unsigned short release_number;
+                       /** Manufacturer String */
+                       wchar_t *manufacturer_string;
+                       /** Product string */
+                       wchar_t *product_string;
+                       /** Usage Page for this Device/Interface
+                           (Windows/Mac only). */
+                       unsigned short usage_page;
+                       /** Usage for this Device/Interface
+                           (Windows/Mac only).*/
+                       unsigned short usage;
+                       /** The USB interface which this logical device
+                           represents. Valid on both Linux implementations
+                           in all cases, and valid on the Windows implementation
+                           only if the device contains more than one interface. */
+                       int interface_number;
+
+                       /** Pointer to the next device */
+                       struct hid_device_info *next;
+               };
+
+
+               /** @brief Initialize the HIDAPI library.
+
+                       This function initializes the HIDAPI library. Calling it is not
+                       strictly necessary, as it will be called automatically by
+                       hid_enumerate() and any of the hid_open_*() functions if it is
+                       needed.  This function should be called at the beginning of
+                       execution however, if there is a chance of HIDAPI handles
+                       being opened by different threads simultaneously.
+                       
+                       @ingroup API
+
+                       @returns
+                               This function returns 0 on success and -1 on error.
+               */
+               int HID_API_EXPORT HID_API_CALL hid_init(void);
+
+               /** @brief Finalize the HIDAPI library.
+
+                       This function frees all of the static data associated with
+                       HIDAPI. It should be called at the end of execution to avoid
+                       memory leaks.
+
+                       @ingroup API
+
+                   @returns
+                               This function returns 0 on success and -1 on error.
+               */
+               int HID_API_EXPORT HID_API_CALL hid_exit(void);
+
+               /** @brief Enumerate the HID Devices.
+
+                       This function returns a linked list of all the HID devices
+                       attached to the system which match vendor_id and product_id.
+                       If @p vendor_id is set to 0 then any vendor matches.
+                       If @p product_id is set to 0 then any product matches.
+                       If @p vendor_id and @p product_id are both set to 0, then
+                       all HID devices will be returned.
+
+                       @ingroup API
+                       @param vendor_id The Vendor ID (VID) of the types of device
+                               to open.
+                       @param product_id The Product ID (PID) of the types of
+                               device to open.
+
+                   @returns
+                       This function returns a pointer to a linked list of type
+                       struct #hid_device, containing information about the HID devices
+                       attached to the system, or NULL in the case of failure. Free
+                       this linked list by calling hid_free_enumeration().
+               */
+               struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id);
+
+               /** @brief Free an enumeration Linked List
+
+                   This function frees a linked list created by hid_enumerate().
+
+                       @ingroup API
+                   @param devs Pointer to a list of struct_device returned from
+                             hid_enumerate().
+               */
+               void  HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs);
+
+               /** @brief Open a HID device using a Vendor ID (VID), Product ID
+                       (PID) and optionally a serial number.
+
+                       If @p serial_number is NULL, the first device with the
+                       specified VID and PID is opened.
+
+                       @ingroup API
+                       @param vendor_id The Vendor ID (VID) of the device to open.
+                       @param product_id The Product ID (PID) of the device to open.
+                       @param serial_number The Serial Number of the device to open
+                                              (Optionally NULL).
+
+                       @returns
+                               This function returns a pointer to a #hid_device object on
+                               success or NULL on failure.
+               */
+               HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number);
+
+               /** @brief Open a HID device by its path name.
+
+                       The path name be determined by calling hid_enumerate(), or a
+                       platform-specific path name can be used (eg: /dev/hidraw0 on
+                       Linux).
+
+                       @ingroup API
+                   @param path The path name of the device to open
+
+                       @returns
+                               This function returns a pointer to a #hid_device object on
+                               success or NULL on failure.
+               */
+               HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path);
+
+               /** @brief Write an Output report to a HID device.
+
+                       The first byte of @p data[] must contain the Report ID. For
+                       devices which only support a single report, this must be set
+                       to 0x0. The remaining bytes contain the report data. Since
+                       the Report ID is mandatory, calls to hid_write() will always
+                       contain one more byte than the report contains. For example,
+                       if a hid report is 16 bytes long, 17 bytes must be passed to
+                       hid_write(), the Report ID (or 0x0, for devices with a
+                       single report), followed by the report data (16 bytes). In
+                       this example, the length passed in would be 17.
+
+                       hid_write() will send the data on the first OUT endpoint, if
+                       one exists. If it does not, it will send the data through
+                       the Control Endpoint (Endpoint 0).
+
+                       @ingroup API
+                       @param device A device handle returned from hid_open().
+                       @param data The data to send, including the report number as
+                               the first byte.
+                       @param length The length in bytes of the data to send.
+
+                       @returns
+                               This function returns the actual number of bytes written and
+                               -1 on error.
+               */
+               int  HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length);
+
+               /** @brief Read an Input report from a HID device with timeout.
+
+                       Input reports are returned
+                       to the host through the INTERRUPT IN endpoint. The first byte will
+                       contain the Report number if the device uses numbered reports.
+
+                       @ingroup API
+                       @param device A device handle returned from hid_open().
+                       @param data A buffer to put the read data into.
+                       @param length The number of bytes to read. For devices with
+                               multiple reports, make sure to read an extra byte for
+                               the report number.
+                       @param milliseconds timeout in milliseconds or -1 for blocking wait.
+
+                       @returns
+                               This function returns the actual number of bytes read and
+                               -1 on error. If no packet was available to be read within
+                               the timeout period, this function returns 0.
+               */
+               int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds);
+
+               /** @brief Read an Input report from a HID device.
+
+                       Input reports are returned
+                   to the host through the INTERRUPT IN endpoint. The first byte will
+                       contain the Report number if the device uses numbered reports.
+
+                       @ingroup API
+                       @param device A device handle returned from hid_open().
+                       @param data A buffer to put the read data into.
+                       @param length The number of bytes to read. For devices with
+                               multiple reports, make sure to read an extra byte for
+                               the report number.
+
+                       @returns
+                               This function returns the actual number of bytes read and
+                               -1 on error. If no packet was available to be read and
+                               the handle is in non-blocking mode, this function returns 0.
+               */
+               int  HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length);
+
+               /** @brief Set the device handle to be non-blocking.
+
+                       In non-blocking mode calls to hid_read() will return
+                       immediately with a value of 0 if there is no data to be
+                       read. In blocking mode, hid_read() will wait (block) until
+                       there is data to read before returning.
+
+                       Nonblocking can be turned on and off at any time.
+
+                       @ingroup API
+                       @param device A device handle returned from hid_open().
+                       @param nonblock enable or not the nonblocking reads
+                        - 1 to enable nonblocking
+                        - 0 to disable nonblocking.
+
+                       @returns
+                               This function returns 0 on success and -1 on error.
+               */
+               int  HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock);
+
+               /** @brief Send a Feature report to the device.
+
+                       Feature reports are sent over the Control endpoint as a
+                       Set_Report transfer.  The first byte of @p data[] must
+                       contain the Report ID. For devices which only support a
+                       single report, this must be set to 0x0. The remaining bytes
+                       contain the report data. Since the Report ID is mandatory,
+                       calls to hid_send_feature_report() will always contain one
+                       more byte than the report contains. For example, if a hid
+                       report is 16 bytes long, 17 bytes must be passed to
+                       hid_send_feature_report(): the Report ID (or 0x0, for
+                       devices which do not use numbered reports), followed by the
+                       report data (16 bytes). In this example, the length passed
+                       in would be 17.
+
+                       @ingroup API
+                       @param device A device handle returned from hid_open().
+                       @param data The data to send, including the report number as
+                               the first byte.
+                       @param length The length in bytes of the data to send, including
+                               the report number.
+
+                       @returns
+                               This function returns the actual number of bytes written and
+                               -1 on error.
+               */
+               int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length);
+
+               /** @brief Get a feature report from a HID device.
+
+                       Set the first byte of @p data[] to the Report ID of the
+                       report to be read.  Make sure to allow space for this
+                       extra byte in @p data[]. Upon return, the first byte will
+                       still contain the Report ID, and the report data will
+                       start in data[1].
+
+                       @ingroup API
+                       @param device A device handle returned from hid_open().
+                       @param data A buffer to put the read data into, including
+                               the Report ID. Set the first byte of @p data[] to the
+                               Report ID of the report to be read, or set it to zero
+                               if your device does not use numbered reports.
+                       @param length The number of bytes to read, including an
+                               extra byte for the report ID. The buffer can be longer
+                               than the actual report.
+
+                       @returns
+                               This function returns the number of bytes read plus
+                               one for the report ID (which is still in the first
+                               byte), or -1 on error.
+               */
+               int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length);
+
+               /** @brief Close a HID device.
+
+                       @ingroup API
+                       @param device A device handle returned from hid_open().
+               */
+               void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device);
+
+               /** @brief Get The Manufacturer String from a HID device.
+
+                       @ingroup API
+                       @param device A device handle returned from hid_open().
+                       @param string A wide string buffer to put the data into.
+                       @param maxlen The length of the buffer in multiples of wchar_t.
+
+                       @returns
+                               This function returns 0 on success and -1 on error.
+               */
+               int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen);
+
+               /** @brief Get The Product String from a HID device.
+
+                       @ingroup API
+                       @param device A device handle returned from hid_open().
+                       @param string A wide string buffer to put the data into.
+                       @param maxlen The length of the buffer in multiples of wchar_t.
+
+                       @returns
+                               This function returns 0 on success and -1 on error.
+               */
+               int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen);
+
+               /** @brief Get The Serial Number String from a HID device.
+
+                       @ingroup API
+                       @param device A device handle returned from hid_open().
+                       @param string A wide string buffer to put the data into.
+                       @param maxlen The length of the buffer in multiples of wchar_t.
+
+                       @returns
+                               This function returns 0 on success and -1 on error.
+               */
+               int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen);
+
+               /** @brief Get a string from a HID device, based on its string index.
+
+                       @ingroup API
+                       @param device A device handle returned from hid_open().
+                       @param string_index The index of the string to get.
+                       @param string A wide string buffer to put the data into.
+                       @param maxlen The length of the buffer in multiples of wchar_t.
+
+                       @returns
+                               This function returns 0 on success and -1 on error.
+               */
+               int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen);
+
+               /** @brief Get a string describing the last error which occurred.
+
+                       @ingroup API
+                       @param device A device handle returned from hid_open().
+
+                       @returns
+                               This function returns a string containing the last error
+                               which occurred or NULL if none has occurred.
+               */
+               HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/main.cpp b/main.cpp
new file mode 100644 (file)
index 0000000..c3449f7
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,1169 @@
+// SVN: $Revision: 61 $
+#include <errno.h>
+#include <iostream>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "error.h"
+#include "USBaccess.h"
+
+typedef enum { O_BRIEF, O_FULL, O_SS } output_t;
+output_t ot = O_FULL;
+
+int retry_count = 10;
+double slp = 0.5;
+CUSBaccess CWusb;
+int USBcount = -1;
+bool initted = false;
+char *path = (char *)"/dev/usb/hiddev";
+bool abrt = false;
+const char *ts = NULL;
+FILE *fh = NULL;
+
+const char *limit_exec_min = NULL, *limit_exec_max = NULL;
+bool limit_min_triggered = false, limit_max_triggered = false;
+double limit_min = 0.0, limit_max = 0.0;
+
+void sigh(int sig)
+{
+       abrt = true;
+
+       fprintf(stderr, "Aborting program\n");
+}
+
+std::string format(const char *fmt, ...)
+{
+       char *buffer = NULL;
+        va_list ap;
+
+        va_start(ap, fmt);
+        (void)vasprintf(&buffer, fmt, ap);
+        va_end(ap);
+
+       std::string result = buffer;
+       free(buffer);
+
+       return result;
+}
+
+std::string time_to_str(double t_in)
+{
+        if (t_in <= 0)
+                return "n/a";
+
+        time_t t = (time_t)t_in;
+        struct tm *tm = localtime(&t);
+        if (!tm)
+                error_exit("localtime(%ld) failed", (long int)t);
+
+        char time_buffer[128];
+        snprintf(time_buffer, sizeof time_buffer, "%04d-%02d-%02dT%02d:%02d:%02d.%03d",
+                tm -> tm_year + 1900,
+                tm -> tm_mon + 1,
+                tm -> tm_mday,
+                tm -> tm_hour,
+                tm -> tm_min,
+                tm -> tm_sec,
+                int((t_in - double(t)) * 1000.0) % 1000);
+
+        return std::string(time_buffer);
+}
+
+void init()
+{
+       if (!initted)
+       {
+               USBcount = CWusb.OpenCleware();
+
+               initted = true;
+       }
+}
+
+const char * device_id_to_string(int id)
+{
+       switch(id)
+       {
+       case CUSBaccess::POWER_DEVICE:
+               return "Power";
+       case CUSBaccess::WATCHDOGXP_DEVICE:
+               return "WatchdogXP";
+       case CUSBaccess::LED_DEVICE:
+               return "LED";
+       case CUSBaccess::WATCHDOG_DEVICE:
+               return "Watchdog";
+       case CUSBaccess::AUTORESET_DEVICE:
+               return "Autoreset device";
+       case CUSBaccess::SWITCH1_DEVICE:
+               return "Switch1";
+       case CUSBaccess::SWITCH2_DEVICE:
+               return "Switch2";
+       case CUSBaccess::SWITCH3_DEVICE:
+               return "Switch3";
+       case CUSBaccess::SWITCH4_DEVICE:
+               return "Switch4";
+       case CUSBaccess::SWITCH5_DEVICE:
+               return "Switch5";
+       case CUSBaccess::SWITCH6_DEVICE:
+               return "Switch6";
+       case CUSBaccess::SWITCH7_DEVICE:
+               return "Switch7";
+       case CUSBaccess::SWITCH8_DEVICE:
+               return "Switch8";
+       case CUSBaccess::SWITCHX_DEVICE:
+               return "SwitchX";
+       case CUSBaccess::TEMPERATURE_DEVICE:
+               return "Temperature sensor";
+       case CUSBaccess::TEMPERATURE2_DEVICE:
+               return "Temperature 2 sensor";
+       case CUSBaccess::TEMPERATURE5_DEVICE:
+               return "Temperature 5 sensor";
+       case CUSBaccess::HUMIDITY1_DEVICE:
+               return "Humidity sensor";
+       case CUSBaccess::CONTACT00_DEVICE:
+               return "Contact 00 device";
+       case CUSBaccess::CONTACT01_DEVICE:
+               return "Contact 01 device";
+       case CUSBaccess::CONTACT02_DEVICE:
+               return "Contact 02 device";
+       case CUSBaccess::CONTACT03_DEVICE:
+               return "Contact 03 device";
+       case CUSBaccess::CONTACT04_DEVICE:
+               return "Contact 04 device";
+       case CUSBaccess::CONTACT05_DEVICE:
+               return "Contact 05 device";
+       case CUSBaccess::CONTACT06_DEVICE:
+               return "Contact 06 device";
+       case CUSBaccess::CONTACT07_DEVICE:
+               return "Contact 07 device";
+       case CUSBaccess::CONTACT08_DEVICE:
+               return "Contact 08 device";
+       case CUSBaccess::CONTACT09_DEVICE:
+               return "Contact 09 device";
+       case CUSBaccess::CONTACT10_DEVICE:
+               return "Contact 10 device";
+       case CUSBaccess::CONTACT11_DEVICE:
+               return "Contact 11 device";
+       case CUSBaccess::CONTACT12_DEVICE:
+               return "Contact 12 device";
+       case CUSBaccess::CONTACT13_DEVICE:
+               return "Contact 13 device";
+       case CUSBaccess::CONTACT14_DEVICE:
+               return "Contact 14 device";
+       case CUSBaccess::CONTACT15_DEVICE:
+               return "Contact 15 device";
+       case CUSBaccess::ENCODER01_DEVICE:
+               return "Encoder 01 device";
+       case CUSBaccess::F4_DEVICE:
+               return "F4 device";
+       case CUSBaccess::KEYC01_DEVICE:
+               return "Keyc01 device";
+       case CUSBaccess::KEYC16_DEVICE:
+               return "Keyc16 device";
+       case CUSBaccess::ADC0800_DEVICE:
+               return "AC0800 device";
+       case CUSBaccess::ADC0801_DEVICE:
+               return "AC0801 device";
+       case CUSBaccess::ADC0802_DEVICE:
+               return "AC0802 device";
+       case CUSBaccess::ADC0803_DEVICE:
+               return "AC0803 device";
+       case CUSBaccess::COUNTER00_DEVICE:
+               return "Counter device";
+       case CUSBaccess::BUTTON_NODEVICE:
+               return "Button no device";
+       }
+
+printf("%d\n", id);
+       return "Device ID not recognised!";
+}
+
+void list_devices()
+{
+       init();
+
+       printf("Cleware library version: %d\n", CWusb.GetDLLVersion());
+        printf("Number of Cleware devices found: %d\n", USBcount);
+
+        for (int devID=0; devID < USBcount; devID++)
+       {
+                int devType = CWusb.GetUSBType(devID);
+
+               printf("Device: %d, type: %s (%d), version: %d, serial number: %d\n",
+                       devID,
+                       device_id_to_string(devType), devType,
+                       CWusb.GetVersion(devID),
+                       CWusb.GetSerialNumber(devID)
+                       );
+       }
+}
+
+#define NO_COMMAND     0
+#define READ_TEMP      1
+#define READ_SWITCH    2
+#define RESET_DEVICE   3
+#define SET_SWITCH     4
+#define READ_HUMIDITY  5
+#define START_DEVICE   6
+#define SET_LED                7
+#define READ_EXTERNAL_SWITCH   8
+#define READ_AUTO_RESET        9
+#define READ_MULTISWITCH       10
+#define SET_MULTISWITCH        11
+#define MULTISWITCH_DIRECTION  12
+#define CONFIGURE_SWITCH       13
+#define READ_COUNTER   14
+#define SET_COUNTER    15
+#define READ_ADC       16
+#define SET_ADC_CHANNEL        17
+
+int find_usb_id(int device_id)
+{
+       for(int devID=0; devID<USBcount; devID++)
+       {
+               if (device_id == -1 || CWusb.GetSerialNumber(devID) == device_id)
+                       return devID;
+       }
+
+       return -1;
+}
+
+int start_tapping_the_watchdog(int device_id)
+{
+       init();
+
+       int usb_id = find_usb_id(device_id);
+
+       if (usb_id == -1)
+               error_exit("Device %d not found!", device_id);
+
+       pid_t pid = fork();
+
+       if (pid == -1)
+       {
+               fprintf(stderr, "Failed to fork");
+               return 1;
+       }
+
+       if (pid == 0)
+       {
+               int err_cnt = 0;
+
+               if (daemon(0, 0) == -1)
+               {
+                       fprintf(stderr, "Failed to become daemon process\n");
+                       return 1;
+               }
+
+               for(;;)
+               {
+                       int time1 = 1, time2 = 5;
+
+                       if (!CWusb.CalmWatchdog(usb_id, time1, time2))
+                       {
+                               err_cnt++;
+
+                               if (err_cnt == 10)
+                                       error_exit("Failed to tap the watchdog 10 times");
+                       }
+
+                       sleep(2);
+               }
+       }
+
+       printf("Watchdog started\n");
+
+       return 0;
+}
+
+void emit(std::string what)
+{
+       if (fh == NULL)
+               std::cout << what;
+       else
+               fprintf(fh, "%s", what.c_str());
+}
+
+void emit_ts()
+{
+       if (ts)
+       {
+               time_t t = time(NULL);
+               struct tm *tm = localtime(&t);
+               char buffer[256];
+
+               strftime(buffer, sizeof buffer, ts, tm);
+
+               emit(format("%s ", buffer));
+       }
+
+}
+
+void init_output()
+{
+       if (ot == O_SS)
+       {
+               emit(format("<?xml version=\"1.0\"?>\n"));
+               emit(format("<?mso-application progid=\"Excel.Sheet\"?>\n"));
+               emit(format("<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\n"));
+               emit(format(" xmlns:x=\"urn:schemas-microsoft-com:office:excel\"\n"));
+               emit(format(" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"\n"));
+               emit(format(" xmlns:html=\"http://www.w3.org/TR/REC-html40\">\n"));
+               emit(format("<DocumentProperties xmlns=\"urn:schemas-microsoft-com:office:office\">\n"));
+               emit(format("<Author>ClewareControl</Author>\n"));
+               emit(format("<Company>folkert@vanheusden.com</Company>\n"));
+               emit(format("<Version>" VERSION "</Version>\n"));
+               emit(format("</DocumentProperties>\n"));
+               emit(format("<Styles>\n"));
+               emit(format("<Style ss:ID=\"sMD\">\n"));
+               emit(format("<NumberFormat ss:Format=\"Long Time\"/>\n"));
+               emit(format("</Style>\n"));
+               emit(format("</Styles>\n"));
+       }
+}
+
+void init_command_output(int command, int dev_serial)
+{
+       if (ot == O_SS)
+       {
+               const char *name = "Cleware";
+
+               switch(command)
+               {
+                       case READ_TEMP:
+                               name = "temperature";
+                               break;
+                       case READ_SWITCH:
+                               name = "read switch";
+                               break;
+                       case RESET_DEVICE:
+                               name = "reset";
+                               break;
+                       case SET_SWITCH:
+                               name = "set switch";
+                               break;
+                       case READ_HUMIDITY:
+                               name = "humitidy";
+                               break;
+                       case START_DEVICE:
+                               name = "start";
+                               break;
+                       case SET_LED:
+                               name = "set led";
+                               break;
+                       case READ_EXTERNAL_SWITCH:
+                               name = "read ext switch";
+                               break;
+                       case READ_AUTO_RESET:
+                               name = "read auto reset";
+                               break;
+                       case READ_MULTISWITCH:
+                               name = "read multisw";
+                               break;
+                       case SET_MULTISWITCH:
+                               name = "set multisw";
+                               break;
+                       case MULTISWITCH_DIRECTION:
+                               name = "multisw dir";
+                               break;
+                       case CONFIGURE_SWITCH:
+                               name = "cfg switch";
+                               break;
+                       case READ_COUNTER:
+                               name = "read counter";
+                               break;
+                       case SET_COUNTER:
+                               name = "set counter";
+                               break;
+                       case READ_ADC:
+                               name = "read adc";
+                               break;
+                       case SET_ADC_CHANNEL:
+                               name = "set adc";
+                               break;
+                       default:
+                               error_exit("Internal error (unknown command)");
+               }
+
+               emit(format("<Worksheet ss:Name=\"%s\">\n", name));
+               emit(format("<Table>\n"));
+               emit(format("<Row>\n"));
+               emit(format("<Cell><Data ss:Type=\"String\">Device serial number:</Data></Cell>\n"));
+               emit(format("<Cell><Data ss:Type=\"String\">%d</Data></Cell>\n", dev_serial));
+               emit(format("</Row>\n"));
+               emit(format("<Row>\n"));
+               emit(format("<Cell><Data ss:Type=\"String\">timestamp</Data></Cell>\n"));
+               emit(format("<Cell><Data ss:Type=\"String\">value</Data></Cell>\n"));
+               emit(format("</Row>\n"));
+       }
+}
+
+void finish_command_output()
+{
+       if (ot == O_SS)
+       {
+                emit(format("</Table>\n"));
+                emit(format("</Worksheet>\n"));
+       }
+}
+
+void finish_output()
+{
+       if (ot == O_SS)
+       {
+               emit(format("</Workbook>\n"));
+       }
+}
+
+void output(std::string descr, double value)
+{
+       if (ot == O_FULL)
+       {
+               emit_ts();
+               emit(format("%s: %f\n", descr.c_str(), value));
+       }
+       else if (ot == O_BRIEF)
+       {
+               emit_ts();
+               emit(format("%f\n", value));
+       }
+       else if (ot == O_SS)
+       {
+                emit(format("<Row>\n"));
+
+                std::string date_str = time_to_str(double(time(NULL)));
+                emit(format("<Cell ss:StyleID=\"sMD\"><Data ss:Type=\"DateTime\">%s</Data></Cell>\n", date_str.c_str()));
+
+               emit(format("<Cell><Data ss:Type=\"Number\">%f</Data></Cell>\n", value));
+
+                emit(format("</Row>\n"));
+       }
+}
+
+void output(std::string descr, int value)
+{
+       if (ot == O_FULL)
+       {
+               emit_ts();
+               emit(format("%s: %d\n", descr.c_str(), value));
+       }
+       else if (ot == O_BRIEF)
+       {
+               emit_ts();
+               emit(format("%d\n", value));
+       }
+       else if (ot == O_SS)
+       {
+                emit(format("<Row>\n"));
+
+                std::string date_str = time_to_str(double(time(NULL)));
+                emit(format("<Cell ss:StyleID=\"sMD\"><Data ss:Type=\"DateTime\">%s</Data></Cell>\n", date_str.c_str()));
+
+               emit(format("<Cell><Data ss:Type=\"Number\">%d</Data></Cell>\n", value));
+
+                emit(format("</Row>\n"));
+       }
+}
+
+void output(std::string descr, std::string value)
+{
+       if (ot == O_FULL)
+       {
+               emit_ts();
+               emit(format("%s: %s\n", descr.c_str(), value.c_str()));
+       }
+       else if (ot == O_BRIEF)
+       {
+               emit_ts();
+               emit(format("%s\n", value.c_str()));
+       }
+       else if (ot == O_SS)
+       {
+                emit(format("<Row>\n"));
+
+                std::string date_str = time_to_str(double(time(NULL)));
+                emit(format("<Cell ss:StyleID=\"sMD\"><Data ss:Type=\"DateTime\">%s</Data></Cell>\n", date_str.c_str()));
+
+               emit(format("<Cell><Data ss:Type=\"String\">%s</Data></Cell>\n", value.c_str()));
+
+                emit(format("</Row>\n"));
+       }
+}
+
+void output(std::string value)
+{
+       if (ot == O_FULL)
+       {
+               emit_ts();
+               emit(format("%s\n", value.c_str()));
+       }
+       else if (ot == O_BRIEF)
+       {
+       }
+       else if (ot == O_SS)
+       {
+                emit(format("<Row>\n"));
+
+                std::string date_str = time_to_str(double(time(NULL)));
+                emit(format("<Cell ss:StyleID=\"sMD\"><Data ss:Type=\"DateTime\">%s</Data></Cell>\n", date_str.c_str()));
+
+               emit(format("<Cell><Data ss:Type=\"String\">%s</Data></Cell>\n", value.c_str()));
+
+                emit(format("</Row>\n"));
+       }
+}
+
+void spawn_script(const char *proc, const char *par)
+{
+       if (ot == O_FULL)
+               fprintf(stderr, "Starting childprocess: %s\n", proc);
+
+       pid_t pid = fork();
+
+       if (pid == -1)
+               fprintf(stderr ,"Failed to fork!\n");
+       else if (pid == 0)
+       {
+               if (-1 == execlp(proc, proc, par, (void *)NULL))
+                       fprintf(stderr, "Failed to execlp(%s)\n", proc);
+
+               exit(1);
+       }
+}
+
+void eval_val(double value)
+{
+       if (limit_exec_min)
+       {
+               if (value < limit_min)
+               {
+                       if (!limit_min_triggered)
+                       {
+                               limit_min_triggered = true;
+
+                               spawn_script(limit_exec_min, format("%f", value).c_str());
+                       }
+               }
+               else
+               {
+                       limit_min_triggered = false;
+               }
+       }
+
+       if (limit_exec_max)
+       {
+               if (value > limit_max)
+               {
+                       if (!limit_max_triggered)
+                       {
+                               limit_max_triggered = true;
+
+                               spawn_script(limit_exec_max, format("%f", value).c_str());
+                       }
+               }
+               else
+               {
+                       limit_max_triggered = false;
+               }
+       }
+}
+
+int do_command(int device_id, int command, int par, int par2, double offset)
+{
+       init();
+
+       int ok = 0;
+       int usb_id = -1, retry;
+
+       if (device_id == -1)
+               fprintf(stderr, "You did not select a device, using first device found.\n");
+
+       usb_id = find_usb_id(device_id);
+
+       if (device_id == -1)
+       {
+               if (usb_id == -1)
+               {
+                       fprintf(stderr, "No device found\n");
+
+                       if (getuid())
+                               fprintf(stderr, "Not running as root: does your current user have enough rights to access the device?\n");
+                       else
+                               fprintf(stderr, "You might need to use -p.\n");
+
+                       exit(1);
+               }
+
+               device_id = CWusb.GetSerialNumber(usb_id);
+
+               if (ot == O_FULL) printf("Using device with serial number: %d\n", device_id);
+       }
+       else if (usb_id == -1)
+       {
+               error_exit("Device %d not found", device_id);
+       }
+
+       init_command_output(command, device_id);
+
+       for(retry=0; (retry<retry_count || retry_count == 0) && abrt == false; retry++)
+       {
+               if (isatty(1) == 0 || fh != NULL)
+                       fprintf(stderr, "%d\r", retry);
+
+               if (command == READ_TEMP)
+               {
+                       double temperature;
+                       static int prev_time = -1;
+                       int time;
+
+                       if (CWusb.GetTemperature(usb_id, &temperature, &time) && time != prev_time)
+                       {
+                               output("Temperature", temperature + offset);
+
+                               eval_val(temperature + offset);
+
+                               ok++;
+                       }
+               }
+               else if (command == READ_SWITCH)
+               {
+                       int status;
+
+                       // if ((status = CWusb.GetSwitch(usb_id, (CUSBaccess::SWITCH_IDs)par)) != -1)
+                       if ((status = CWusb.GetSeqSwitch(usb_id, (CUSBaccess::SWITCH_IDs)par, 0)) != -1)
+                       {
+                               output("Status", format("%s (%d)", status?"On":"Off", status));
+
+                               ok++;
+                       }
+               }
+               else if (command == RESET_DEVICE)
+               {
+                       if (CWusb.ResetDevice(usb_id))
+                       {
+                               output("Device resetted");
+
+                               ok++;
+                       }
+               }
+               else if (command == SET_SWITCH)
+               {
+                       if (CWusb.SetSwitch(usb_id, (CUSBaccess::SWITCH_IDs)par, par2))
+                       {
+                               output(format("Switch %d", par - 16), format("set to %s", par2?"On":"Off"));
+
+                               ok++;
+                       }
+               }
+               else if (command == READ_HUMIDITY)
+               {
+                       double humidity;
+                       static int prev_time = -1;
+                       int time;
+
+                       if (CWusb.GetHumidity(usb_id, &humidity, &time) && prev_time != time)
+                       {
+                               output("Humidity", humidity + offset);
+
+                               eval_val(humidity + offset);
+
+                               ok++;
+                       }
+               }
+               else if (command == START_DEVICE)
+               {
+                       if (CWusb.StartDevice(usb_id))
+                       {
+                               output("Device started");
+
+                               ok++;
+                       }
+               }
+               else if (command == SET_LED)
+               {
+                       if (CWusb.SetLED(usb_id, (CUSBaccess::LED_IDs)par, par2))
+                       {
+                               output(format("LED %d", par), format("set to %d", par2));
+                               ok++;
+                       }
+               }
+               else if (command == READ_EXTERNAL_SWITCH)
+               {
+                       output("Switched on count", CWusb.GetManualOnCount(usb_id));
+                       output("Switched on duration ", CWusb.GetManualOnTime(usb_id));
+
+                       ok++;
+               }
+               else if (command == READ_AUTO_RESET)
+               {
+                       output("Auto reset count", CWusb.GetOnlineOnCount(usb_id));
+                       output("Auto reset duration", CWusb.GetOnlineOnTime(usb_id));
+
+                       ok++;
+               }
+               else if (command == READ_MULTISWITCH)
+               {
+                       unsigned long int value = 0;
+
+                       if (CWusb.GetMultiSwitch(usb_id, NULL, &value, 0))
+                       {
+                               std::string bits;
+                               for(int loop=15; loop>=0; loop--)
+                               {
+                                       if (value & (1 << loop))
+                                               bits += "1";
+                                       else
+                                               bits += "0";
+                               }
+
+                               output("Statusses of lines", bits);
+
+                               ok++;
+                       }
+               }
+               else if (command == SET_MULTISWITCH)
+               {
+                       if (CWusb.SetMultiSwitch(usb_id, par) == 0)
+                       {
+                               output("Bit-pattern set.");
+
+                               ok++;
+                       }
+               }
+               else if (command == MULTISWITCH_DIRECTION)
+               {
+                       if (CWusb.SetMultiConfig(usb_id, par) == 0)
+                       {
+                               output("Directions set.");
+
+                               ok++;
+                       }
+               }
+               else if (command == CONFIGURE_SWITCH)
+               {
+                       int type = CWusb.GetUSBType(usb_id);
+
+                       if (type == CUSBaccess::WATCHDOG_DEVICE  ||
+                                       type == CUSBaccess::AUTORESET_DEVICE ||
+                                       type == CUSBaccess::SWITCH1_DEVICE)
+                       {
+                               if (par == 0 ||
+                                               par == 1 ||
+                                               par == 2 ||
+                                               par == 3)
+                               {
+                                       unsigned char buf[3];
+
+                                       buf[0] = CUSBaccess::EEwrite;
+                                       buf[1] = 2;
+                                       buf[2] = par;  // =watchdog, 1=autoreset, 2=switch, 3=switch ATXX
+                                       CWusb.SetLED(usb_id, CUSBaccess::LED_3, 7);
+                                       CWusb.SetValue(usb_id, buf, 3);
+                                       CWusb.SetLED(usb_id, CUSBaccess::LED_3, 0);
+
+                                       fprintf(stderr, "Now first unplug (and replug) the device before use!\n");
+
+                                       ok++;
+                               }
+                               else
+                               {
+                                       fprintf(stderr, "%d is not a valid setting. Valid parameters: 0 (watchdog), 1 (autoreset), 2 (switch) and 3 (switch ATXX)\n", par);
+                               }
+                       }
+                       else
+                       {
+                               fprintf(stderr, "One can only perform this action a watchdog-, an autoreset- or a switch device!\n");
+                       }
+               }
+               else if (command == READ_COUNTER)
+               {
+                       int value = CWusb.GetCounter(usb_id, (CUSBaccess::COUNTER_IDs)par);
+
+                       output("Counter", value);
+
+                       eval_val(value);
+
+                       ok++;
+               }
+               else if (command == SET_ADC_CHANNEL)
+               {
+                       if (CWusb.ResetDevice(usb_id) == 0)
+                               fprintf(stderr, "Failed resetting device, channel switch failed\n");
+                       else
+                       {
+                               unsigned char buf[3] = { 0 };
+
+                               if (par == 0)
+                                       buf[0] = 6;
+                               else if (par == 1)
+                               {
+                                       buf[0] = 5;
+                                       buf[1] = 1;
+                               }
+                               else
+                               {
+                                       fprintf(stderr, "Only channel 0 or 1 are supported\n");
+                               }
+
+                               if (buf[0])
+                               {
+                                       if (CWusb.SetValue(usb_id, buf, 3) == 0)
+                                               fprintf(stderr, "Problem setting ADC channel\n");
+                                       else
+                                       {
+                                               output(format("Channel %d selected", par));
+                                               ok++;
+                                       }
+                               }
+                       }
+               }
+               else if (command == READ_ADC)
+               {
+                       double scale = -1.0;
+                       if (par == 0)
+                               scale = 5.181;
+                       else if (par == 1)
+                               scale = 13.621;
+                       else if (par == 2)
+                               scale = 24.704;
+                       else
+                               fprintf(stderr, "Second parameter must be either 0, 1 or 2. See help (-h).\n");
+
+                       if (scale > 0)
+                       {
+                               unsigned char buf[4];
+                               if (CWusb.GetValue(usb_id, buf, sizeof buf) == 0)
+                                       fprintf(stderr, "Problem retrieving measurement\n");
+                               else
+                               {
+                                       unsigned char nibble1 = buf[2 + 0] & 0x0f;
+                                       unsigned char nibble2 = buf[2 + 1] >> 4;
+                                       unsigned char nibble3 = buf[2 + 1] & 0x0f;
+
+                                       double value = (nibble1 << 8) + (nibble2) + (nibble3 << 4);
+                                       value *= scale / double(0xfff);
+
+                                       eval_val(value);
+
+                                       output("Voltage", value);
+
+                                       ok++;
+                               }
+                       }
+               }
+               else if (command == SET_COUNTER)
+               {
+                       if (CWusb.SetCounter(usb_id, par2, (CUSBaccess::COUNTER_IDs)par) < 0)
+                               fprintf(stderr, "Failed to set counter %d\n", par);
+
+                       output(format("Counter %d set", par));
+
+                       ok++;
+               }
+               else
+               {
+                       error_exit("Internal error! (unknown command %d)", command);
+               }
+
+               if ((retry < retry_count - 1 || retry_count == 0) && slp > 0.0)
+                       usleep(useconds_t(slp * 1000000.0));
+       }
+
+       if (ok == 0)
+               fprintf(stderr, "Failed to access device %d\n", CWusb.GetSerialNumber(usb_id));
+       else if (ok != retry_count)
+               fprintf(stderr, "Occasionally (%d/%d) failed to access device %d\n", ok, retry_count, CWusb.GetSerialNumber(usb_id));
+
+       finish_command_output();
+
+       return ok ?  0 : -1;
+}
+
+void version(void)
+{
+       fprintf(stderr, "clewarecontrol " VERSION ", (C) 2005-2013 by folkert@vanheusden.com\n");
+       fprintf(stderr, "SVN revision: $Revision: 61 $\n");
+}
+
+void usage(void)
+{
+       version();
+
+       fprintf(stderr, "\n");
+
+       fprintf(stderr, "-p x     set path to look for hiddevx devices. normally they're found in /dev/usb (default) or /dev Use this as first parameter!\n");
+       fprintf(stderr, "-l       list devices\n");
+       fprintf(stderr, "-d x     use device with serial number 'x' for the next operations\n");
+       fprintf(stderr, "-c x     number of times to repeat the command: 0 for keep running\n");
+       fprintf(stderr, "-i x     delay between each command invocation\n");
+       fprintf(stderr, "-t       add a timestamp before each line (in seconds since 1970), also see -T\n");
+       fprintf(stderr, "-T x     add a timestamp before each line, x defines the format. see \"man strftime\" for supported parameters\n");
+       fprintf(stderr, "-rt      read temperature\n");
+       fprintf(stderr, "-rh      read humidity\n");
+       fprintf(stderr, "-rs x    read switch 'x'\n");
+       fprintf(stderr, "-rp      read external switch\n");
+       fprintf(stderr, "-rr      shows how often the auto-reset kicked in\n");
+       fprintf(stderr, "-rm      read states of the USB-IO16 lines\n");
+       fprintf(stderr, "-rc x    read counter (x= 0 or 1)\n");
+       fprintf(stderr, "-ra x    read ADC, x=0 for 5.181V, 1 for 13.621V and 2 for 24.704\n");
+       fprintf(stderr, "-ar      reset device\n");
+       fprintf(stderr, "-as x y  set switch x to y (0=off, 1=on)\n");
+       fprintf(stderr, "-ag      start device\n");
+       fprintf(stderr, "-al x y  set led x to y (0...15)\n");
+       fprintf(stderr, "-am x    set the states of the USB-IO16 lines: x must be a hexvalue\n");
+       fprintf(stderr, "-ad x    set the directions of the USB-IO16 lines (hexvalue)\n");
+       fprintf(stderr, "-ac x y  set counter x to y (x= 0 or 1)\n");
+       fprintf(stderr, "-ai x    set ADC channel, x is either 0 or 1\n");
+       fprintf(stderr, "-cfg x   configure the device to be a watchdog (0), autoreset (1), switch (2) or switch ATXX (3)\n");
+       fprintf(stderr, "-w       become daemon-process that pats the watchdog\n");
+       fprintf(stderr, "-o x     offset to add to values\n");
+       fprintf(stderr, "-O x     output type (brief (former -b), readable (default), spreadsheet (xml spreadsheet, compatible with e.g. openoffice and microsoft excel)\n");
+       fprintf(stderr, "-f x     send output to file (only measured data, errors are emitted to your console/terminal)\n");
+       fprintf(stderr, "-mintrig x y  if the value read (temperature, humidity, counter, ADC) becomes less than x, then spawn process y\n");
+       fprintf(stderr, "-maxtrig x y  if the value read (temperature, humidity, counter, ADC) becomes bigger than x, then spawn process y\n");
+       fprintf(stderr, "-F       fork into the background (become daemon)\n");
+}
+
+int main(int argc, char *argv[])
+{
+       int loop, device_id = -1;
+       int par = -1, par2 = -1;
+       double offset = 0.0;
+
+       if (argc < 2)
+       {
+               usage();
+               return 1;
+       }
+
+       signal(SIGCHLD, SIG_IGN);
+       signal(SIGINT, sigh);
+
+       for(loop=1; loop<argc; loop++)
+       {
+               if (strcmp(argv[loop], "-l") == 0)
+               {
+                       list_devices();
+                       return 0;
+               }
+               else if (strcmp(argv[loop], "-F") == 0)
+               {
+                       if (daemon(-1, 0) == -1)
+                               error_exit("Failed to become daemon process");
+               }
+               else if (strcmp(argv[loop], "-f") == 0)
+               {
+                       fh = fopen(argv[++loop], "wb");
+                       if (!fh)
+                               error_exit("Failed to create file %s", argv[loop]);
+               }
+               else if (strcmp(argv[loop], "-p") == 0)
+               {
+                       char *par = argv[++loop];
+                       path = (char *)malloc(strlen(par) + 16);
+                       sprintf(path, "%s/hiddev", par);
+               }
+               else if (strcmp(argv[loop], "-o") == 0)
+               {
+                       offset = atof(argv[++loop]);
+               }
+               else if (strcmp(argv[loop], "-i") == 0)
+               {
+                       slp = atof(argv[++loop]);
+               }
+               else if (strcmp(argv[loop], "-t") == 0)
+               {
+                       ts = "%s";
+               }
+               else if (strcmp(argv[loop], "-T") == 0)
+               {
+                       ts = argv[++loop];
+               }
+               else if (strcmp(argv[loop], "-d") == 0)
+               {
+                       device_id = atoi(argv[++loop]);
+               }
+               else if (strcmp(argv[loop], "-O") == 0)
+               {
+                       const char *fmt = argv[++loop];
+
+                       if (strcasecmp(fmt, "brief") == 0)
+                               ot = O_BRIEF;
+                       else if (strcasecmp(fmt, "readable") == 0 || strcasecmp(fmt, "full") == 0)
+                               ot = O_FULL;
+                       else if (strcasecmp(fmt, "spreadsheet") == 0 || strcasecmp(fmt, "xml") == 0)
+                               ot = O_SS;
+                       else
+                       {
+                               fprintf(stderr, "Output format \"%s\" is not recognized\n", fmt);
+                               usage();
+                               return 1;
+                       }
+
+                       init_output();
+               }
+               else if (strcmp(argv[loop], "-c") == 0)
+               {
+                       retry_count = atoi(argv[++loop]);
+               }
+               else if (strcmp(argv[loop], "-rt") == 0)
+               {
+                       if (do_command(device_id, READ_TEMP, -1, -1, offset))
+                               return 1;
+               }
+               else if (strcmp(argv[loop], "-rs") == 0)
+               {
+                       par = atoi(argv[++loop]);
+                       if (par < 16)
+                               par += 16;
+                       if (do_command(device_id, READ_SWITCH, par, -1, -1000.0))
+                               return 1;
+               }
+               else if (strcmp(argv[loop], "-ar") == 0)
+               {
+                       if (do_command(device_id, RESET_DEVICE, -1, -1, -1000.0))
+                               return 1;
+               }
+               else if (strcmp(argv[loop], "-ra") == 0)
+               {
+                       par = atoi(argv[++loop]);
+                       if (do_command(device_id, READ_ADC, par, -1, -1000.0))
+                               return 1;
+               }
+               else if (strcmp(argv[loop], "-ai") == 0)
+               {
+                       par = atoi(argv[++loop]);
+                       if (do_command(device_id, SET_ADC_CHANNEL, par, -1, -1000.0))
+                               return 1;
+               }
+               else if (strcmp(argv[loop], "-as") == 0)
+               {
+                       par = atoi(argv[++loop]);
+                       if (par < 16)
+                               par += 16;
+                       par2 = atoi(argv[++loop]);
+                       if (do_command(device_id, SET_SWITCH, par, par2, -1000.0))
+                               return 1;
+               }
+               else if (strcmp(argv[loop], "-al") == 0)
+               {
+                       par = atoi(argv[++loop]);
+                       par2 = atoi(argv[++loop]);
+
+                       if (do_command(device_id, SET_LED, par, par2, -1000.0))
+                               return 1;
+               }
+               else if (strcmp(argv[loop], "-ac") == 0)
+               {
+                       par = atoi(argv[++loop]);
+                       par2 = atoi(argv[++loop]);
+
+                       if (do_command(device_id, SET_COUNTER, par, par2, -1000.0))
+                               return 1;
+               }
+               else if (strcmp(argv[loop], "-mintrig") == 0)
+               {
+                       double trigger_val = atof(argv[++loop]);
+                       const char *cmd = argv[++loop];
+
+                       limit_exec_min = cmd;
+                       limit_min = trigger_val;
+               }
+               else if (strcmp(argv[loop], "-maxtrig") == 0)
+               {
+                       double trigger_val = atof(argv[++loop]);
+                       const char *cmd = argv[++loop];
+
+                       limit_exec_max = cmd;
+                       limit_max = trigger_val;
+               }
+               else if (strcmp(argv[loop], "-rh") == 0)
+               {
+                       if (do_command(device_id, READ_HUMIDITY, -1, -1, offset))
+                               return 1;
+               }
+               else if (strcmp(argv[loop], "-ag") == 0)
+               {
+                       if (do_command(device_id, START_DEVICE, -1, -1, -1000.0))
+                               return 1;
+               }
+               else if (strcmp(argv[loop], "-w") == 0)
+               {
+                       if (start_tapping_the_watchdog(device_id))
+                               return 1;
+               }
+               else if (strcmp(argv[loop], "-rp") == 0)
+               {
+                       if (do_command(device_id, READ_EXTERNAL_SWITCH, -1, -1, -1000.0))
+                               return 1;
+               }
+               else if (strcmp(argv[loop], "-rr") == 0)
+               {
+                       if (do_command(device_id, READ_AUTO_RESET, -1, -1, -1000.0))
+                               return 1;
+               }
+               else if (strcmp(argv[loop], "-rm") == 0)
+               {
+                       if (do_command(device_id, READ_MULTISWITCH, -1, -1, -1000.0))
+                               return 1;
+               }
+               else if (strcmp(argv[loop], "-rc") == 0)
+               {
+                       par = strtol(argv[++loop], NULL, 10);
+                       if (do_command(device_id, READ_COUNTER, par, -1, -1000.0))
+                               return 1;
+               }
+               else if (strcmp(argv[loop], "-am") == 0)
+               {
+                       par = strtol(argv[++loop], NULL, 16);
+                       if (do_command(device_id, SET_MULTISWITCH, par, -1, -1000.0))
+                               return 1;
+               }
+               else if (strcmp(argv[loop], "-ad") == 0)
+               {
+                       par = strtol(argv[++loop], NULL, 16);
+                       if (do_command(device_id, MULTISWITCH_DIRECTION, par, -1, -1000.0))
+                               return 1;
+               }
+               else if (strcmp(argv[loop], "-cfg") == 0)
+               {
+                       par = atoi(argv[++loop]);
+                       if (do_command(device_id, CONFIGURE_SWITCH, par, -1, -1000.0))
+                               return 1;
+               }
+               else if (strcmp(argv[loop], "-h") == 0)
+               {
+                       usage();
+                       return 0;
+               }
+               else if (strcmp(argv[loop], "-V") == 0)
+               {
+                       version();
+                       return 0;
+               }
+               else
+               {
+                       fprintf(stderr, "Switch '%s' is not recognized.\n", argv[loop]);
+                       return 1;
+               }
+       }
+
+       finish_output();
+
+       if (fh)
+       {
+               fsync(fileno(fh));
+
+               fclose(fh);
+       }
+
+       CWusb.CloseCleware();
+
+       return 0;
+}
diff --git a/readme-mac.txt b/readme-mac.txt
new file mode 100644 (file)
index 0000000..89a5fd4
--- /dev/null
@@ -0,0 +1,100 @@
+requirements
+------------
+No extra software is required.
+
+
+who/what/where
+--------------
+clewarecontrol is written by Folkert van Heusden.
+It is specifically meant to control Cleware devices from within MacOS X.
+Please do NOT contact cleware if you have problems with this software on your
+Mac, contact me instead at: mail@vanheusden.com
+Please note that I'm a busy man so it may take a bit before I respond.
+
+
+usage
+-----
+Clewarecontrol is a command-line program. You can run it from within e.g. the
+"terminal"-program.
+
+To see a list of options, invoke:
+       clewarecontrol -h
+
+To, for example, see a list of all Cleware devices connected to your mac, run:
+       clewarecontrol -l
+
+Please also check the website for tips and help.
+
+
+devices
+-------
+- temperature sensor
+       clewarecontrol -rt
+
+- humidity sensor
+  This device needs to be "started" first, then you can read sensor readings
+       clewarecontrol -ag -rh
+
+- 2 channel AD converter (analog to digital)
+  First you need to know what it range it works: 5v, 13v or 24v
+  then you must select the channel to read from - the device has 2 channels
+  after selecting the channel, you can keep reading
+       clewarecontrol -ai x        where x is 0 or 1 (selects channel)
+       clewarecontrol -ra y        where y is 0 voor 5v, 1 for 13v, etc.
+- Ampel ("Switch1 (8)")
+  The traffic light is, from clewarecontrol seen, a device with 3 switches in
+  it that can be individiually switched on and off
+       clewarecontrol -as x y      where x is 0, 1 or 2 (0=red, 2=green) and
+                                    y is 0 or 1 (0 is off)
+
+- IO16 ("Contact 00 device (48)")
+  The IO16 is a 16 port I/O interface. You can configure each pin to be either
+  input or output. This setting is stored in an eprom so that a pin cannot
+  become accidently output while you expected an input.
+  Set the direction with:
+       clewarecontrol -ad x        where x is a hex value representing a 1
+                                    or 0 selecting the direction
+  After that you can set the output pins to 1 or 0 with:
+       clewarecontrol -am x        where is a hex value
+
+- Luminus
+  This is in fact an AD converter with integrated hardware which measures the
+  amount of light. It has 1 chnanel, so you don't need to select it (like the
+  generic ADC). Reading values (in version 2.5) can be perfomed like his:
+       clewarecontrol -ra 0
+  This gives a value between 0 and 5. I (developer of this Linux program)
+  need to buy a lux meter to scale this correctly.
+
+
+- USB-cutter
+  This is a device which is at its heart a switch like the other switches.
+  To use it, you need to start it:
+       clewarecontrol -ag
+  then, you can toggle the USB status like this:
+       clewarecontrol -as 0 1      this will "cut" the USB device (switching
+                                   it off)
+       clewarecontrol -as 0 0      this will enable the USB device again(!)
+  indeed, the logic is inverted.
+
+
+-mintrig / -maxtrig
+-------------------
+Run the program with -c 0 so that it keeps running forever (unless you want to
+have it monitor the value for a shorter time).
+Also start it with -F so that it runs in the background.
+Then set the -mintrig or -maxtrig switches.
+As the last parameter, set the sensor to monitor: -rh (humidity), -rt
+(temperature), etc.
+For example:
+       clewarecontrol -c 0 -maxtrig 0.5 ./myscript.sh -ra 0
+If the ADC tells us that the voltage is over 0.5 volts, then "myscript.sh" is
+invoked. As a parameter, the script will get the measured value.
+
+
+miscellaneous
+-------------
+I would be delighted if you share your experiences with me!
+
+Please note: this software contains "hidapi". The original hidapi can be
+retrieved from http://www.signal11.us/oss/hidapi/
diff --git a/readme-perl.txt b/readme-perl.txt
new file mode 100644 (file)
index 0000000..94c0265
--- /dev/null
@@ -0,0 +1,11 @@
+To build the Perl code:
+ - install the swig package
+   on Debian this is valled "swig"
+
+ - run:
+       make cleware_perl
+   this will produce: cleware.so and cleware.pm
+   These two files must be installed in your Perl system.
+
+ - look at example.pl to see how it works (e.g. execute perl example.pl)
+   make sure that the user you run your scripts with has enough rights to access the USB devices!
diff --git a/readme-python.txt b/readme-python.txt
new file mode 100644 (file)
index 0000000..62c9fed
--- /dev/null
@@ -0,0 +1,14 @@
+To build the Python code:
+ - install the Python development package
+   on Debian this is called e.g. "python2.7-dev" or "python3.2-dev"
+
+ - install the swig package
+   on Debian this is valled "swig"
+
+ - run:
+       make cleware_python
+   this will produce: _cleware.so and cleware.py.
+   These two files must be installed in your Python system.
+
+ - look at example.py to see how it works (e.g. execute python example.py)
+   make sure that the user you run your scripts with has enough rights to access the USB devices!
diff --git a/readme.txt b/readme.txt
new file mode 100644 (file)
index 0000000..d2f0b78
--- /dev/null
@@ -0,0 +1,158 @@
+build instructions
+------------------
+Required libraries:
+       libhidapi-dev
+
+Since version 4.0 clewarecontrol uses this library to abstract the
+interfacing with the kernel. That way it may work on other OSes and new(er)
+kernel as well.
+
+Installation:
+       make install
+
+
+usage
+-----
+Please see the man-page for help on how to use it:
+       make clewarecontrol
+
+or run the program with the -h switch:
+       clewarecontrol -h
+
+Please also check the website for tips and help.
+
+
+devices
+-------
+- temperature sensor
+       clewarecontrol -rt
+
+- humidity sensor
+  This device needs to be "started" first, then you can read sensor readings
+       clewarecontrol -ag -rh
+
+- 2 channel AD converter (analog to digital)
+  First you need to know what it range it works: 5v, 13v or 24v
+  then you must select the channel to read from - the device has 2 channels
+  after selecting the channel, you can keep reading
+       clewarecontrol -ai x        where x is 0 or 1 (selects channel)
+       clewarecontrol -ra y        where y is 0 voor 5v, 1 for 13v, etc.
+- Ampel ("Switch1 (8)")
+  The traffic light is, from clewarecontrol seen, a device with 3 switches in
+  it that can be individiually switched on and off
+       clewarecontrol -as x y      where x is 0, 1 or 2 (0=red, 2=green) and
+                                    y is 0 or 1 (0 is off)
+
+- IO16 ("Contact 00 device (48)")
+  The IO16 is a 16 port I/O interface. You can configure each pin to be either
+  input or output. This setting is stored in an eprom so that a pin cannot
+  become accidently output while you expected an input.
+  Set the direction with:
+       clewarecontrol -ad x        where x is a hex value representing a 1
+                                    or 0 selecting the direction
+  After that you can set the output pins to 1 or 0 with:
+       clewarecontrol -am x        where is a hex value
+
+- Luminus
+  This is in fact an AD converter with integrated hardware which measures the
+  amount of light. It has 1 chnanel, so you don't need to select it (like the
+  generic ADC). Reading values (in version 2.5) can be perfomed like his:
+       clewarecontrol -ra 0
+  This gives a value between 0 and 5. I (developer of this Linux program)
+  need to buy a lux meter to scale this correctly.
+
+
+- USB-cutter
+  This is a device which is at its heart a switch like the other switches.
+  To use it, you need to start it:
+       clewarecontrol -ag
+  then, you can toggle the USB status like this:
+       clewarecontrol -as 0 1      this will "cut" the USB device (switching
+                                   it off)
+       clewarecontrol -as 0 0      this will enable the USB device again(!)
+  indeed, the logic is inverted.
+
+
+-mintrig / -maxtrig
+-------------------
+Run the program with -c 0 so that it keeps running forever (unless you want to
+have it monitor the value for a shorter time).
+Also start it with -F so that it runs in the background.
+Then set the -mintrig or -maxtrig switches.
+As the last parameter, set the sensor to monitor: -rh (humidity), -rt
+(temperature), etc.
+For example:
+       clewarecontrol -c 0 -maxtrig 0.5 ./myscript.sh -ra 0
+If the ADC tells us that the voltage is over 0.5 volts, then "myscript.sh" is
+invoked. As a parameter, the script will get the measured value.
+
+
+I would be delighted if you share your experiences with me!
+
+
+python library
+--------------
+please see readme-python.txt for details on how to create and use the python
+library.
+
+
+perl library
+--------------
+please see readme-perl.txt for details on how to create and use the perl
+library.
+
+
+problems
+--------
+If you encounter any problems when using clewarecontrol with Cleware devices,
+DO NOT contact Cleware but please contact me: folkert@vanheusden.com
+
+Of course you can always write me when you have questions/suggestions/etc.
+ folkert@vanheusden.com
+
+
+FAQ
+---
+Q1. Values retrieved are invalid
+A1. Occasionally the values retrieved are invalid. E.g. a temperature of 170
+    degrees and such. In that case you can reset the device (might need to
+    reset it multiple times!) and then it'll work
+
+Q2. It does not compile on SuSE Enterprise Linux 10
+A2. Insert in file USBaccessBasic.c at line 17 (that is BEFORE the line
+    including usbdevice_fs.h!) the following line:
+       #define __user
+
+Q3. clewarecontrol -l doesn't list any devices
+A3. The Cleware USB library expects the following files to exist:
+       crw-rw-rw- 1 root root 180,  96 May  9  2005 /dev/usb/hiddev0
+       crw-rw-rw- 1 root root 180,  97 May  9  2005 /dev/usb/hiddev1
+       ...
+       crw-rw-rw- 1 root root 180, 110 May  9  2005 /dev/usb/hiddev14
+       crw-rw-rw- 1 root root 180, 111 May  9  2005 /dev/usb/hiddev15
+
+    Since version 1.2 you can use -p to select a different path, eg.:
+       clewarecontrol -p /dev -l
+
+    Make sure the user you're running clewarecontrol from has enought rights
+    to access the devices. For starters, to see if it works at all, run it as
+    root.
+
+Q4. clewarecontrol still can't find any devices
+A4. If that still does not give any output then please e-mail me the output of
+    the following commands:
+       uname -a
+       lsusb
+       lsmod
+       strace clewarecontrol -l
+       ps -deaf | grep udev
+       find /dev -name hiddev\*
+
+    Please also tell me what distribution (e.g. redhat/suse/ubuntu) and what
+    version you're using
+
+
+Regards,
+
+Folkert van Heusden
diff --git a/setup.py b/setup.py
new file mode 100644 (file)
index 0000000..ab7d7d6
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+
+from distutils.core import setup, Extension
+
+cleware_module = Extension('_cleware',
+                           sources=['cleware_wrap.cxx', 'USBaccessBasic.cpp', 'USBaccess.cpp'],
+                           )
+
+setup (name = 'cleware',
+       version = '2.3',
+       author      = "Folkert van Heusden",
+       description = """Cleware library bindings for Python""",
+       ext_modules = [cleware_module],
+       py_modules = ["cleware"],
+       )
diff --git a/setup.py_CI b/setup.py_CI
new file mode 100644 (file)
index 0000000..59168ea
--- /dev/null
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+from distutils.core import setup, Extension
+
+cleware_module = Extension('_cleware',
+                           sources=['cleware_wrap.cxx', 'USBaccessBasic.cpp', 'USBaccess.cpp'],
+                           libraries = ['perl', 'hidapi-libusb'],
+                           )
+
+setup (name = 'cleware',
+       version = '2.3',
+       author      = "Folkert van Heusden",
+       description = """Cleware library bindings for Python""",
+       ext_modules = [cleware_module],
+       py_modules = ["cleware"],
+       )