summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDonghoon Shin <dhs.shin@samsung.com>2016-09-19 17:36:01 +0900
committerDonghoon Shin <dhs.shin@samsung.com>2016-09-19 17:36:01 +0900
commite8acd13cc87ea038ecd6103e4088ce3cf5d501d7 (patch)
tree4c7c8cc683a297463996aa286f2f7758e8691b8f
parentb95c2492274542bc4718a863f5d88f37a0a788ab (diff)
downloadclewarecontrol-release-20160930.tar.gz
clewarecontrol-release-20160930.tar.bz2
clewarecontrol-release-20160930.zip
Change-Id: I59bac2188ffbfe5a2ad2d9dcb33847aabfaffe44
-rw-r--r--LICENSE662
-rw-r--r--Makefile51
-rw-r--r--Makefile-mac39
-rw-r--r--README.md168
-rw-r--r--USBaccess.cpp1189
-rw-r--r--USBaccess.h131
-rw-r--r--USBaccessBasic.cpp521
-rw-r--r--USBaccessBasic.h87
-rw-r--r--circle.yml70
-rw-r--r--cleware.i252
-rw-r--r--clewarecontrol.1110
-rw-r--r--debian/changelog5
-rw-r--r--debian/compat1
-rw-r--r--debian/control14
-rw-r--r--debian/copyright638
-rw-r--r--debian/docs9
-rw-r--r--debian/files1
-rwxr-xr-xdebian/rules8
-rw-r--r--debian/source/format1
-rw-r--r--error.cpp21
-rw-r--r--error.h2
-rwxr-xr-xexample.pl254
-rwxr-xr-xexample.py149
-rw-r--r--examples/Munin/cleware-munin.sh30
-rwxr-xr-xexamples/Nagios/RCS/cleware_nagios_script,v40
-rwxr-xr-xexamples/Nagios/cleware_nagios_script34
-rw-r--r--examples/Nagios/nagios.txt42
-rw-r--r--examples/Nagios/seealso.txt4
-rwxr-xr-xexamples/RRD/add_measurement_to_rrd5
-rwxr-xr-xexamples/RRD/draw_graph_from_rrd5
-rwxr-xr-xexamples/RRD/make_rrd3
-rw-r--r--examples/RRD/rrd.txt34
-rwxr-xr-xexamples/Watchdog/clewarewatchdog34
-rw-r--r--examples/Watchdog/watchdog.txt19
-rw-r--r--examples/ampel/ampel.txt18
-rwxr-xr-xexamples/ampel/script.sh6
-rwxr-xr-xinstall-lib.pl19
-rwxr-xr-xinstall-lib.py19
-rw-r--r--mac-hidapi/hid.c1112
-rw-r--r--mac-hidapi/hidapi.h391
-rw-r--r--main.cpp1169
-rw-r--r--readme-mac.txt100
-rw-r--r--readme-perl.txt11
-rw-r--r--readme-python.txt14
-rw-r--r--readme.txt158
-rw-r--r--setup.py15
-rw-r--r--setup.py_CI16
47 files changed, 7681 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
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
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
index 0000000..428e498
--- /dev/null
+++ b/Makefile-mac
@@ -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
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
index 0000000..708596f
--- /dev/null
+++ b/USBaccess.cpp
@@ -0,0 +1,1189 @@
+// Basic class implementation for access to USB HID devices
+//
+// (C) 2001 Copyright Cleware GmbH
+// All rights reserved
+//
+// History:
+// 05.01.01 ws Initial coding
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include "USBaccess.h"
+#include "USBaccessBasic.h"
+
+
+CUSBaccess::CUSBaccess() {
+ cwInitCleware() ;
+ }
+
+CUSBaccess::~CUSBaccess() {
+ }
+
+
+// returns number of found Cleware devices
+int
+CUSBaccess::OpenCleware() {
+ int rval = cwOpenCleware(NULL) ;
+
+ return rval ;
+ }
+
+int
+CUSBaccess::Recover(int devNum) {
+ int rval = cwRecover(devNum) ;
+
+ return rval ;
+ }
+
+// return true if ok, else false
+int
+CUSBaccess::CloseCleware() {
+ int rval = 1 ;
+
+ cwCloseCleware() ;
+
+ return rval ;
+ }
+
+HANDLE
+CUSBaccess::GetHandle(int deviceNo) {
+ return cwGetHandle(deviceNo) ;
+ }
+
+int
+CUSBaccess::GetVersion(int deviceNo) {
+ return cwGetVersion(deviceNo) ;
+ }
+
+int
+CUSBaccess::GetUSBType(int deviceNo) {
+ int devType = (USBtype_enum)cwGetUSBType(deviceNo) ;
+ int devVersion = cwGetVersion(deviceNo) ;
+ if (devType == CONTACT00_DEVICE && devVersion <= 12 && devVersion > 5) {
+ // this may be an early switch3/4 build on base of contact HW - adjust the ID
+ int switchCount = 0 ;
+ for (int autoCnt=4 ; autoCnt > 0 ; autoCnt--) {
+ const int bufSize = 6 ;
+ unsigned char buf[bufSize] = { 0, 0, 0, 0, 0, 0 } ;
+ int seqNumber = SyncDevice(deviceNo, 0xffff) ;
+ Sleep(20) ;
+
+ for (int securityCnt=50 ; switchCount == 0 && seqNumber != 0 && securityCnt > 0 ; securityCnt--) {
+ if (GetValue(deviceNo, buf, bufSize)) {
+ if (buf[1] == seqNumber) {
+ switchCount = buf[0] & 0x7f ;
+ break ;
+ }
+ }
+ else {
+ securityCnt /= 10 ; // don't wait too long if GetValue failed
+ Sleep(20) ;
+ }
+ }
+ }
+ if (switchCount > 0 && switchCount <= 8)
+ devType = SWITCHX_DEVICE ;
+ }
+ return devType ;
+ }
+
+int
+CUSBaccess::GetSerialNumber(int deviceNo) {
+ return cwGetSerialNumber(deviceNo) ;
+ }
+
+
+
+// returns 1 if ok or 0 in case of an error
+int
+CUSBaccess::GetValue(int deviceNo, unsigned char *buf, int bufsize) {
+ int rval = cwGetValue(deviceNo, buf, bufsize) ;
+
+ return rval ;
+ }
+
+
+int
+CUSBaccess::SetValue(int deviceNo, unsigned char *buf, int bufsize) {
+ int rval = cwSetValue(deviceNo, buf, bufsize) ;
+
+ return rval ;
+ }
+
+int
+CUSBaccess::SetLED(int deviceNo, enum LED_IDs Led, int value) {
+ unsigned char s[6] ;
+ int rval = 0 ;
+
+ USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;
+ int version = cwGetVersion(deviceNo) ;
+
+ if (devType == LED_DEVICE && version <= 10) {
+ s[0] = Led ;
+ s[1] = value ;
+ rval = SetValue(deviceNo, s, 2) ;
+ }
+ else if (devType == TEMPERATURE2_DEVICE || devType == HUMIDITY1_DEVICE) {
+ s[0] = 0 ;
+ s[1] = Led ;
+ s[2] = value ;
+ s[3] = 0 ;
+ rval = SetValue(deviceNo, s, 4) ;
+ }
+ else if (devType == ENCODER01_DEVICE) {
+ s[0] = 0 ;
+ s[1] = Led ;
+ s[2] = value ;
+ s[3] = 0 ;
+ s[4] = 0 ;
+ s[5] = 0 ;
+ rval = SetValue(deviceNo, s, 6) ;
+ }
+ else if ((devType == CONTACT00_DEVICE && version > 6) || devType == KEYC01_DEVICE || devType == KEYC16_DEVICE || devType == WATCHDOGXP_DEVICE || devType == SWITCHX_DEVICE) { // 5 bytes to send
+ s[0] = 0 ;
+ s[1] = Led ;
+ s[2] = value ;
+ s[3] = 0 ;
+ s[4] = 0 ;
+ rval = SetValue(deviceNo, s, 5) ;
+ }
+ else {
+ s[0] = 0 ;
+ s[1] = Led ;
+ s[2] = value ;
+ rval = SetValue(deviceNo, s, 3) ;
+ }
+
+ return rval ;
+ }
+
+int
+CUSBaccess::SetSwitch(int deviceNo, enum SWITCH_IDs Switch, int On) {
+ unsigned char s[6] ;
+ int rval = 0 ;
+ int version = cwGetVersion(deviceNo) ;
+
+ if (Switch < SWITCH_0 || Switch > SWITCH_15)
+ return -1 ;
+
+ USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;
+ if (devType == SWITCH1_DEVICE || devType == AUTORESET_DEVICE || devType == WATCHDOG_DEVICE) {
+ s[0] = 0 ;
+ s[1] = Switch ;
+ if (version < 4) // old version do not invert
+ s[2] = !On ;
+ else
+ s[2] = On ;
+ rval = SetValue(deviceNo, s, 3) ;
+ if (rval && Switch == SWITCH_0) { // set LED for first switch
+ if (On) {
+ SetLED(deviceNo, LED_0, 0) ; // USB Switch will invert LED
+ SetLED(deviceNo, LED_1, 15) ;
+ }
+ else {
+ SetLED(deviceNo, LED_0, 15) ;
+ SetLED(deviceNo, LED_1, 0) ;
+ }
+ }
+ }
+ else if (devType == SWITCHX_DEVICE || devType == WATCHDOGXP_DEVICE || (devType == CONTACT00_DEVICE && version > 6)) { // 5 bytes to send
+ int mask = 1 << (Switch - SWITCH_0) ; // setup mask
+ int data = 0 ;
+ if (On)
+ data = mask ;
+// LINUX sign bit problem
+ s[0] = 3 << 4 ;
+ if (data & 0x8000)
+ s[0] |= 0x08 ;
+ if (data & 0x80)
+ s[0] |= 0x04 ;
+ if (mask & 0x8000)
+ s[0] |= 0x02 ;
+ if (mask & 0x80)
+ s[0] |= 0x01 ;
+ s[1] = (unsigned char)(data >> 8) & 0x7f ;
+ s[2] = (unsigned char)(data & 0xff) & 0x7f ;
+ s[3] = (unsigned char)(mask >> 8) & 0x7f ;
+ s[4] = (unsigned char)(mask & 0xff) & 0x7f ;
+/* old code, may cause Linux sign problem
+ if (GetHWversion(deviceNo) == 0)
+ s[0] = 3 ;
+ else
+ s[0] = ContactWrite ;
+ s[1] = data >> 8 ;
+ s[2] = data & 0xff ;
+ s[3] = mask >> 8 ;
+ s[4] = mask & 0xff ;
+*/
+ rval = SetValue(deviceNo, s, 5) ;
+ }
+ else if (devType == ENCODER01_DEVICE) {
+ s[0] = 0 ;
+ s[1] = Switch ;
+ s[2] = On ;
+ s[3] = 0 ;
+ s[4] = 0 ;
+ s[5] = 0 ;
+ rval = SetValue(deviceNo, s, 6) ;
+ }
+ else if (devType == COUNTER00_DEVICE) {
+ s[0] = 0 ;
+ s[1] = Switch ;
+ s[2] = On ;
+ rval = SetValue(deviceNo, s, 3) ;
+ }
+ else
+ rval = -1 ;
+
+ return rval ;
+ }
+
+int // 0=error, else=ok
+CUSBaccess::GetSwitchConfig(int deviceNo, int *switchCount, int *buttonAvailable) {
+ const int bufSize = 6 ;
+ unsigned char buf[bufSize] = { 0, 0, 0, 0, 0, 0 } ;
+ int ok = 0 ;
+ USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;
+ int version = cwGetVersion(deviceNo) ;
+
+ if ((devType == CONTACT00_DEVICE && version >= 5) || devType == SWITCHX_DEVICE || devType == WATCHDOGXP_DEVICE) {
+ *switchCount = 0 ;
+ for (int autoCnt=4 ; autoCnt > 0 ; autoCnt--) {
+ int seqNumber = SyncDevice(deviceNo, 0xffff) ;
+ Sleep(20) ;
+
+ for (int securityCnt=50 ; seqNumber != 0 && securityCnt > 0 ; securityCnt--) {
+ if (GetValue(deviceNo, buf, bufSize)) {
+ if (buf[1] == seqNumber) {
+ ok = 1 ;
+ *switchCount = buf[0] & 0x7f ;
+ break ;
+ }
+ }
+ else {
+ securityCnt /= 10 ; // don't wait too long if GetValue failed
+ Sleep(20) ;
+ }
+ }
+ if (ok >= 0)
+ break ;
+ }
+ if (buttonAvailable)
+ *buttonAvailable = 0 ;
+ return ok ;
+ }
+
+ if (devType == COUNTER00_DEVICE) {
+ *switchCount = 2 ;
+ if (buttonAvailable)
+ *buttonAvailable = 0 ;
+ return ok ;
+ }
+
+ if ( devType == SWITCH1_DEVICE
+ || devType == AUTORESET_DEVICE
+ || devType == WATCHDOG_DEVICE
+ || devType == F4_DEVICE) {
+ *switchCount = 1 ;
+ *buttonAvailable = 0 ;
+ if (version >= 10) {
+ if (ok = GetValue(deviceNo, buf, bufSize) && (buf[0] & 0x80)) {
+ *switchCount = 1 ;
+ if (buf[0] & 0x02)
+ *switchCount = 2 ;
+ if (buf[0] & 0x08)
+ *switchCount = 3 ;
+ if (buf[0] & 0x20) {
+ if (*switchCount == 3)
+ *switchCount = 4 ; // only single switches may have a start button
+ else
+ *buttonAvailable = 1 ;
+ }
+ }
+ }
+ else
+ ok = 1 ;
+ }
+
+ return ok ;
+ }
+
+int // On 0=off, 1=on, -1=error
+CUSBaccess::GetSwitch(int deviceNo, enum SWITCH_IDs Switch) {
+ const int bufSize = 6 ;
+ unsigned char buf[bufSize] ;
+ int ok = 0 ;
+ USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;
+
+ if ( devType != SWITCH1_DEVICE
+ && devType != AUTORESET_DEVICE
+ && devType != WATCHDOG_DEVICE
+ && devType != WATCHDOGXP_DEVICE
+ && devType != F4_DEVICE
+ && devType != SWITCHX_DEVICE
+ && devType != CONTACT00_DEVICE
+ && devType != COUNTER00_DEVICE
+ && devType != ENCODER01_DEVICE)
+ return -1 ;
+
+ if (Switch < SWITCH_0 || Switch > SWITCH_15)
+ return -1 ;
+
+ int version = cwGetVersion(deviceNo) ;
+
+ if ((devType == CONTACT00_DEVICE && version > 6) || devType == SWITCHX_DEVICE || devType == WATCHDOGXP_DEVICE) { // 5 bytes to send
+ unsigned long int mask = 1 << (Switch - SWITCH_0) ; // setup mask
+ unsigned long int data = 0 ;
+ ok = GetMultiSwitch(deviceNo, &mask, &data, 0) ; // mask is change ,ask on return
+ mask = 1 << (Switch - SWITCH_0) ; // setup mask
+ if (ok >= 0)
+ ok = (data & mask) ? 1 : 0 ;
+ }
+
+ else if (1 || version < 10) { // else only if in separate thread
+ if (GetValue(deviceNo, buf, bufSize)) {
+ int mask = 1 << ((Switch - SWITCH_0) * 2) ;
+ if (version >= 10 || devType == CONTACT00_DEVICE || devType == COUNTER00_DEVICE || devType == F4_DEVICE)
+ ok = (buf[0] & mask) ? 1 : 0 ;
+ else // old switch
+ ok = (buf[2] & mask) ? 1 : 0 ;
+ }
+ else
+ ok = -1 ; // getvalue failed - may be disconnected
+
+ if (ok >= 0 && version < 4 && devType != CONTACT00_DEVICE && devType != COUNTER00_DEVICE&& devType != F4_DEVICE)
+ ok = !ok ;
+ }
+ else { // new version - ask for online count to get a fast answer (use this only if in separate thread)
+ static int sequenceNumber = 1 ;
+
+ buf[0] = GetInfo ;
+ buf[1] = OnlineCount ;
+ buf[2] = sequenceNumber ;
+ SetValue(deviceNo, buf, 3) ;
+ for (int timeout=25 ; timeout > 0 ; timeout--) {
+ Sleep(25) ;
+ if (GetValue(deviceNo, buf, bufSize)) {
+ if ((buf[0] & 0x80) == 0) // valid bit
+ continue ;
+ if (buf[1] != ( (sequenceNumber & 0x1f) << 3 ) + OnlineCount)
+ continue ;
+ ok = buf[0] & 1 ;
+ break ;
+ }
+ }
+
+ sequenceNumber = (++sequenceNumber) & 0x1f ;
+ }
+
+ return ok ;
+ }
+
+int // On 0=off, 1=on, -1=error ; the seqNum is generated by the Start command.
+CUSBaccess::GetSeqSwitch(int deviceNo, enum SWITCH_IDs Switch, int seqNumber) {
+ const int bufSize = 6 ;
+ unsigned char buf[bufSize] ;
+ int ok = 0 ;
+ USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;
+
+ if ( devType != SWITCH1_DEVICE
+ && devType != AUTORESET_DEVICE
+ && devType != WATCHDOG_DEVICE
+ && devType != F4_DEVICE
+ && devType != CONTACT00_DEVICE
+ && devType != SWITCHX_DEVICE
+ && devType != COUNTER00_DEVICE
+ && devType != ENCODER01_DEVICE)
+ return -1 ;
+
+ if (Switch < SWITCH_0 || Switch > SWITCH_15)
+ return -1 ;
+
+ int version = cwGetVersion(deviceNo) ;
+ if (version < 20 && devType != CONTACT00_DEVICE && devType != SWITCHX_DEVICE && devType != COUNTER00_DEVICE && devType != F4_DEVICE)
+ return -1 ;
+
+ if (seqNumber == 0) // do this internally
+ seqNumber = StartDevice(deviceNo) ;
+
+ buf[1] = 0 ;
+ for (int securityCnt=20 ; buf[1] != seqNumber && securityCnt > 0 ; securityCnt--) {
+ if (GetValue(deviceNo, buf, bufSize)) {
+ int mask = 1 << ((Switch - SWITCH_0) * 2) ;
+ ok = (buf[0] & mask) ? 1 : 0 ;
+ }
+ else {
+ ok = -1 ; // getvalue failed - may be disconnected
+ break ;
+ }
+ }
+
+ return ok ;
+ }
+
+int // rval seqNum = ok, -1 = error
+CUSBaccess::GetMultiSwitch(int deviceNo, unsigned long int *mask, unsigned long int *value, int seqNumber) {
+ unsigned char buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 } ;
+ int bufSize ;
+ int ok = -1 ;
+ int automatic = 0 ;
+
+ USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;
+ int version = cwGetVersion(deviceNo) ;
+
+ if (devType == KEYC16_DEVICE)
+ bufSize = 8 ;
+ else if (devType == CONTACT00_DEVICE || devType == KEYC01_DEVICE || devType == SWITCHX_DEVICE || devType == WATCHDOGXP_DEVICE) {
+ if (version < 5)
+ return -1 ;
+ bufSize = 6 ;
+ }
+ else
+ return -1 ;
+
+ if (value == 0)
+ return -1 ;
+
+ if (seqNumber == 0) // do this internally
+ automatic = 1 ;
+
+ int readMask = 0 ;
+ if (mask)
+ readMask = *mask ;
+ if (readMask == 0)
+ readMask = 0xffff ; // get every single bit!!
+
+ for (int autoCnt=4 ; autoCnt > 0 ; autoCnt--) {
+ if (automatic) {
+ seqNumber = SyncDevice(deviceNo, readMask) ;
+ Sleep(20) ;
+ }
+
+ for (int securityCnt=50 ; seqNumber != 0 && securityCnt > 0 ; securityCnt--) {
+ if (GetValue(deviceNo, buf, bufSize)) {
+ if (mask != 0)
+ *mask = (buf[2] << 8) + buf[3] ;
+ unsigned long int v = (buf[4] << 8) + buf[5] ;
+ if (version < 7 && devType != KEYC16_DEVICE && devType != KEYC01_DEVICE)
+ *value = 0xffff & ~v ;
+ else
+ *value = v ;
+ if (buf[1] == seqNumber) {
+ ok = seqNumber ;
+ break ;
+ }
+ // Sleep(50) ; don't sleep - we just killing the USB fifo
+ }
+ else {
+ securityCnt /= 10 ; // don't wait too long if GetValue failed
+ Sleep(20) ;
+ }
+ }
+ if (ok >= 0 || automatic == 0)
+ break ;
+ }
+
+ return ok ;
+ }
+
+int // On 0=ok, -1=error
+CUSBaccess::SetMultiSwitch(int deviceNo, unsigned long int value) {
+ const int bufSize = 5 ;
+ unsigned char buf[bufSize] ;
+ int ok = -1 ;
+ USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;
+
+ if (devType != CONTACT00_DEVICE && devType != SWITCHX_DEVICE && devType != WATCHDOGXP_DEVICE)
+ return -1 ;
+
+ int version = cwGetVersion(deviceNo) ;
+ if (version < 5)
+ return -1 ;
+
+/* orginal
+ buf[0] = 3 ;
+ buf[1] = (unsigned char)(value >> 8) ;
+ buf[2] = (unsigned char)(value & 0xff) ;
+ buf[3] = 0xff ;
+ buf[4] = 0xff ;
+*/
+// LINUX sign bit problem
+ buf[0] = 3 << 4 ;
+ if (value & 0x8000)
+ buf[0] |= 0x08 ;
+ if (value & 0x80)
+ buf[0] |= 0x04 ;
+ buf[0] |= 3 ; // mask bits
+ buf[1] = (unsigned char)(value >> 8) & 0x7f ;
+ buf[2] = (unsigned char)(value & 0xff) & 0x7f ;
+ buf[3] = 0x7f ;
+ buf[4] = 0x7f ;
+
+ if (SetValue(deviceNo, buf, version > 6 ? 5 : 3))
+ ok = 0 ;
+
+ return ok ;
+ }
+
+int // On 0=ok, -1=error
+CUSBaccess::SetMultiConfig(int deviceNo, unsigned long int directions) { // 1=input, 0=output
+ const int bufSize = 5 ;
+ unsigned char buf[bufSize] ;
+ int ok = -1 ;
+ USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;
+
+ if (devType != CONTACT00_DEVICE && devType != SWITCHX_DEVICE && devType != WATCHDOGXP_DEVICE)
+ return -1 ;
+
+ int version = cwGetVersion(deviceNo) ;
+ if (version < 5)
+ return -1 ;
+
+/* orginal
+ if (version < 10)
+ buf[0] = KeepCalm ; // dirty old code
+ else
+ buf[0] = Configure ;
+ buf[1] = (unsigned char)(directions >> 8) ;
+ buf[2] = (unsigned char)(directions & 0xff) ;
+ buf[3] = 0 ;
+ buf[4] = 0 ;
+*/
+// LINUX sign bit problem
+ if (version < 10)
+ buf[0] = 4 << 4 ; // dirty old code
+ else
+ buf[0] = 7 << 4 ;
+ if (directions & 0x8000)
+ buf[0] |= 0x08 ;
+ if (directions & 0x80)
+ buf[0] |= 0x04 ;
+ buf[1] = (unsigned char)(directions >> 8) & 0x7f ;
+ buf[2] = (unsigned char)(directions & 0xff) & 0x7f ;
+ buf[3] = 0 ;
+ buf[4] = 0 ;
+
+ if (SetValue(deviceNo, buf, version > 6 ? 5 : 3))
+ ok = 0 ;
+
+ return ok ;
+ }
+
+int // // return value of counter (0 or 1 for USB-IO16) or -1 in case of an error
+CUSBaccess::GetCounter(int deviceNo, enum COUNTER_IDs counterID) {
+ const int bufSize = 6 ;
+ unsigned char buf[bufSize] ;
+ int rval = -1 ;
+ int automatic = 0 ;
+ static int sequenceNumber = 1 ;
+ int sendlen = bufSize ;
+ int isIO16 = false ;
+
+// original
+// sequenceNumber = (++sequenceNumber) & 0xff ;
+ if (++sequenceNumber > 0x7f) // LINUX sign bit problem
+ sequenceNumber = 1 ;
+
+ USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;
+ int version = cwGetVersion(deviceNo) ;
+
+ if (devType == CONTACT00_DEVICE) {
+ sendlen = 5 ;
+ if (version >= 6)
+ isIO16 = true ;
+ }
+ else if (devType == COUNTER00_DEVICE)
+ sendlen = 3 ;
+ else
+ return -1 ;
+
+ for (int autoCnt=4 ; autoCnt > 0 ; autoCnt--) {
+ buf[0] = CUSBaccess::GetInfo ;
+ buf[1] = sequenceNumber ;
+ buf[2] = 0 ;
+ buf[3] = 0 ;
+ buf[4] = 0 ;
+
+ if (!SetValue(deviceNo, buf, sendlen)) {
+ Sleep(50) ;
+ continue ;
+ }
+ Sleep(20) ;
+
+ buf[1] = 0 ;
+ for (int securityCnt=50 ; securityCnt > 0 ; securityCnt--) {
+ if (GetValue(deviceNo, buf, bufSize)) {
+ if (isIO16 && buf[0] != 0xff) { // 0xff indicates that the counters are prepared
+ Sleep(10) ;
+ continue ;
+ }
+ if (buf[1] != sequenceNumber) {
+ Sleep(10) ;
+ continue ;
+ }
+ if (!isIO16)
+ rval = (buf[2] << 24) + (buf[3] << 16) + (buf[4] << 8) + buf[5] ;
+ else {
+ if (counterID == 0)
+ rval = (buf[2] << 8) + buf[3] ;
+ else
+ rval = (buf[4] << 8) + buf[5] ;
+ }
+ break ;
+ // Sleep(50) ; don't sleep - we just killing the USB fifo
+ }
+ else {
+ securityCnt /= 10 ; // don't wait too long if GetValue failed
+ Sleep(20) ;
+ }
+ }
+ if (rval >= 0)
+ break ;
+ }
+
+ return rval ;
+ }
+
+int
+CUSBaccess::SetCounter(int deviceNo, int counter, enum COUNTER_IDs counterID) { // -1=error, COUNTER_IDs ununsed until now
+ const int bufSize = 3 ;
+ unsigned char buf[bufSize] ;
+ int ok = -1 ;
+ int automatic = 0 ;
+
+ USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;
+ int version = cwGetVersion(deviceNo) ;
+
+ if (devType == COUNTER00_DEVICE) {
+ buf[0] = CUSBaccess::Configure ;
+ buf[1] = counter >> 8 ;
+ buf[2] = counter & 0xff ;
+ if (SetValue(deviceNo, buf, bufSize))
+ ok = 0 ;
+ }
+
+ return ok ;
+ }
+
+
+int // returns how often switch is manually turned on, -1 in case of an error
+CUSBaccess::GetManualOnCount(int deviceNo) {
+ const int bufSize = 6 ;
+ unsigned char buf[bufSize] ;
+ int rval = -1 ;
+ USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;
+ static int sequenceNumber = 1 ;
+
+ if ( ( devType == SWITCH1_DEVICE
+ || devType == AUTORESET_DEVICE
+ || devType == WATCHDOG_DEVICE)
+ && cwGetVersion(deviceNo) >= 10) {
+ for (int timeout=5 ; timeout > 0 ; timeout--) {
+ buf[0] = GetInfo ;
+ buf[1] = ManualCount ;
+ buf[2] = sequenceNumber ;
+ SetValue(deviceNo, buf, 3) ;
+ for (int timeout2=3 ; timeout2 > 0 ; timeout2--) {
+ Sleep(50) ;
+ if (GetValue(deviceNo, buf, bufSize)) {
+ if ((buf[0] & 0x80) == 0) // valid bit
+ continue ;
+ if (buf[1] != ( (sequenceNumber & 0x1f) << 3 ) + ManualCount)
+ continue ;
+ if ((buf[5] & 0x80) == 0) // valid data bit
+ continue ;
+ rval = buf[2] + (buf[3] << 8) + (buf[4] << 16) + ((buf[5] & 0x7f) << 24) ;
+ break ;
+ }
+ }
+ if (rval != -1)
+ break ;
+ Sleep(250) ;
+ }
+ }
+
+ sequenceNumber = (++sequenceNumber) & 0x1f ;
+
+ return rval ;
+ }
+
+int // returns how long (seconds) switch is manually turned on, -1 in case of an error
+CUSBaccess::GetManualOnTime(int deviceNo) {
+ const int bufSize = 6 ;
+ unsigned char buf[bufSize] ;
+ int rval = -1 ;
+ USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;
+ static int sequenceNumber = 1 ;
+
+ if ( ( devType == SWITCH1_DEVICE
+ || devType == AUTORESET_DEVICE
+ || devType == WATCHDOG_DEVICE)
+ && cwGetVersion(deviceNo) >= 10) {
+ for (int timeout=5 ; timeout > 0 ; timeout--) {
+ buf[0] = GetInfo ;
+ buf[1] = ManualTime ;
+ buf[2] = sequenceNumber ;
+ SetValue(deviceNo, buf, 3) ;
+ for (int timeout2=3 ; timeout2 > 0 ; timeout2--) {
+ Sleep(50) ;
+ if (GetValue(deviceNo, buf, bufSize)) {
+ if ((buf[0] & 0x80) == 0) // valid bit
+ continue ;
+ if (buf[1] != ( (sequenceNumber & 0x1f) << 3 ) + ManualTime)
+ continue ;
+ if ((buf[5] & 0x80) == 0) // valid data bit
+ continue ;
+ rval = buf[2] + (buf[3] << 8) + (buf[4] << 16) + ((buf[5] & 0x7f) << 24) ;
+ break ;
+ }
+ }
+ if (rval != -1)
+ break ;
+ Sleep(250) ;
+ }
+ }
+
+ if (rval >= 0) { // rval is 256 * 1,024 ms
+ double u_seconds = 256. * 1024. ;
+ u_seconds *= rval ;
+ rval = (int) (u_seconds / 1000000) ;
+ }
+
+ sequenceNumber = (++sequenceNumber) & 0x1f ;
+
+ return rval ;
+ }
+
+int // returns how often switch is turned on by USB command, -1 in case of an error
+CUSBaccess::GetOnlineOnCount(int deviceNo) {
+ const int bufSize = 6 ;
+ unsigned char buf[bufSize] ;
+ int rval = -1 ;
+ USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;
+ static int sequenceNumber = 1 ;
+ int timeout=-1, timeout2=-1 ;
+
+ cwDebugWrite("GetOnlineCount\n") ;
+
+ if ( ( devType == SWITCH1_DEVICE
+ || devType == AUTORESET_DEVICE
+ || devType == WATCHDOGXP_DEVICE
+ || devType == WATCHDOG_DEVICE)
+ && cwGetVersion(deviceNo) >= 10) {
+ for (timeout=5 ; timeout > 0 ; timeout--) {
+ buf[0] = GetInfo ;
+ if (devType == WATCHDOGXP_DEVICE) {
+ buf[1] = sequenceNumber ;
+ SetValue(deviceNo, buf, 5) ;
+ }
+ else {
+ buf[1] = OnlineCount ;
+ buf[2] = sequenceNumber ;
+ SetValue(deviceNo, buf, 3) ;
+ }
+ for (timeout2=3 ; timeout2 > 0 ; timeout2--) {
+ Sleep(50) ;
+ if (GetValue(deviceNo, buf, bufSize)) {
+ if ((buf[0] & 0x80) == 0) // valid bit
+ continue ;
+ if (devType == WATCHDOGXP_DEVICE) {
+ if (buf[1] != sequenceNumber)
+ continue ;
+ }
+ else {
+ if (buf[1] != ( (sequenceNumber & 0x1f) << 3 ) + OnlineCount)
+ continue ;
+ }
+ if ((buf[5] & 0x80) == 0) // valid data bit
+ continue ;
+ rval = buf[2] + (buf[3] << 8) + (buf[4] << 16) + ((buf[5] & 0x7f) << 24) ;
+ break ;
+ }
+ }
+ if (rval != -1)
+ break ;
+ Sleep(250) ;
+ }
+ }
+
+ static char ds[256] ;
+ sprintf(ds, "GetOnlineOnCount(%d) %s, seq=%d, time1=%d, time2=%d\n",
+ deviceNo, (rval==-1)?"failed":"ok", sequenceNumber, timeout, timeout2) ;
+ cwDebugWrite(ds) ;
+
+ sequenceNumber = (++sequenceNumber) & 0x1f ;
+
+ cwDebugWrite("GetOnlineCout\n") ;
+
+ return rval ;
+ }
+
+int // returns how long (seconds) switch is turned on by USB command, -1 in case of an error
+CUSBaccess::GetOnlineOnTime(int deviceNo) {
+ const int bufSize = 6 ;
+ unsigned char buf[bufSize] ;
+ int rval = -1 ;
+ USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;
+ static int sequenceNumber = 1 ;
+
+ if ( ( devType == SWITCH1_DEVICE
+ || devType == AUTORESET_DEVICE
+ || devType == WATCHDOG_DEVICE)
+ && cwGetVersion(deviceNo) >= 10) {
+ for (int timeout=5 ; timeout > 0 ; timeout--) {
+ buf[0] = GetInfo ;
+ buf[1] = OnlineTime ;
+ buf[2] = sequenceNumber ;
+ SetValue(deviceNo, buf, 3) ;
+ for (int timeout2=3 ; timeout2 > 0 ; timeout2--) {
+ Sleep(50) ;
+ if (GetValue(deviceNo, buf, bufSize)) {
+ if ((buf[0] & 0x80) == 0) // valid bit
+ continue ;
+ if (buf[1] != ( (sequenceNumber & 0x1f) << 3 ) + OnlineTime)
+ continue ;
+ if ((buf[5] & 0x80) == 0) // valid data bit
+ continue ;
+ rval = buf[2] + (buf[3] << 8) + (buf[4] << 16) + ((buf[5] & 0x7f) << 24) ;
+ break ;
+ }
+ }
+ if (rval != -1)
+ break ;
+ Sleep(250) ;
+ }
+ }
+
+ if (rval >= 0) { // rval is 256 * 1,024 ms
+ double u_seconds = 256. * 1024. ;
+ u_seconds *= rval ;
+ rval = (int) (u_seconds / 1000000) ;
+ }
+
+ sequenceNumber = (++sequenceNumber) & 0x1f ;
+
+ return rval ;
+ }
+
+int
+CUSBaccess::ResetDevice(int deviceNo) {
+ int ok = 1 ;
+ const int bufsize = 6 ;
+ unsigned char buf[bufsize] ;
+ int version = cwGetVersion(deviceNo) ;
+
+ buf[0] = CUSBaccess::Reset ;
+ buf[1] = 0 ;
+ buf[2] = 0 ;
+ buf[3] = 0 ;
+ buf[4] = 0 ;
+ buf[5] = 0 ;
+ int type = (USBtype_enum)cwGetUSBType(deviceNo) ;
+ if (type == TEMPERATURE2_DEVICE || type == HUMIDITY1_DEVICE)
+ ok = SetValue(deviceNo, buf, 4) ;
+ else if ((type == CONTACT00_DEVICE && version > 6) || type == SWITCHX_DEVICE || type == WATCHDOGXP_DEVICE || type == KEYC01_DEVICE || type == KEYC16_DEVICE)
+ ok = SetValue(deviceNo, buf, bufsize) ;
+ else if (type == ENCODER01_DEVICE)
+ ok = SetValue(deviceNo, buf, bufsize) ;
+ else
+ ok = SetValue(deviceNo, buf, 3) ;
+
+ return ok ;
+ }
+
+int
+CUSBaccess::StartDevice(int deviceNo) { // mask in case of CONTACT00-device
+ int ok = 1 ;
+ const int bufsize = 5 ;
+ unsigned char buf[bufsize] ;
+ static int sequenceNumber = 1 ;
+
+/* orginal
+ sequenceNumber = (++sequenceNumber) & 0xff ;
+ if (sequenceNumber == 0)
+ sequenceNumber = 1 ;
+*/
+ if (++sequenceNumber > 0x7f) // LINUX sign bit problem
+ sequenceNumber = 1 ;
+
+ buf[0] = CUSBaccess::StartMeasuring ;
+ buf[1] = sequenceNumber ;
+ buf[2] = 0 ;
+ buf[3] = 0 ;
+ buf[4] = 0 ;
+
+ int type = (USBtype_enum)cwGetUSBType(deviceNo) ;
+ int version = cwGetVersion(deviceNo) ;
+
+ if (type == TEMPERATURE2_DEVICE || type == HUMIDITY1_DEVICE)
+ ok = SetValue(deviceNo, buf, 4) ;
+ else if ((type == CONTACT00_DEVICE && version > 6) || type == SWITCHX_DEVICE || type == WATCHDOGXP_DEVICE || type == KEYC01_DEVICE || type == KEYC16_DEVICE)
+ ok = SetValue(deviceNo, buf, 5) ;
+ else
+ ok = SetValue(deviceNo, buf, 3) ;
+
+ return (ok ? sequenceNumber : 0) ;
+ }
+
+int
+CUSBaccess::SyncDevice(int deviceNo, unsigned long int mask) { // mask in case of CONTACT00-device
+ int ok = 1 ;
+ const int bufsize = 5 ;
+ unsigned char buf[bufsize] ;
+ static int sequenceNumber = 1 ;
+
+/* orginal
+ sequenceNumber = (++sequenceNumber) & 0xff ;
+ if (sequenceNumber == 0)
+ sequenceNumber = 1 ;
+*/
+ if (++sequenceNumber > 0x7f) // LINUX signed byte
+ sequenceNumber = 1 ;
+
+ if (mask == 0)
+ mask = 0xffff ; // get every single bit!!
+
+/* orginal
+ buf[0] = CUSBaccess::StartMeasuring ;
+ buf[1] = sequenceNumber ;
+ buf[2] = 0 ;
+ buf[3] = (unsigned char)(mask >> 8) ;
+ buf[4] = (unsigned char)(mask & 0xff) ;
+*/
+// LINUX sign bit problem
+ buf[0] = CUSBaccess::StartMeasuring << 4 ;
+ if (mask & 0x8000)
+ buf[0] |= 0x02 ;
+ if (mask & 0x80)
+ buf[0] |= 0x01 ;
+ // buf[0] = CUSBaccess::StartMeasuring ;
+ buf[1] = sequenceNumber ;
+ buf[2] = 0 ;
+ buf[3] = (unsigned char)(mask >> 8) & 0x7f ;
+ buf[4] = (unsigned char)(mask & 0xff) & 0x7f ;
+
+ int type = (USBtype_enum)cwGetUSBType(deviceNo) ;
+ int version = cwGetVersion(deviceNo) ;
+
+ if ((type == CONTACT00_DEVICE&& version > 6) || type == SWITCHX_DEVICE || type == WATCHDOGXP_DEVICE || type == KEYC01_DEVICE || type == KEYC16_DEVICE)
+ ok = SetValue(deviceNo, buf, 5) ;
+
+ return (ok ? sequenceNumber : 0) ;
+ }
+
+int
+CUSBaccess::CalmWatchdog(int deviceNo, int minutes, int minutes2restart) {
+ int ok = 0 ;
+ const int bufsize = 5 ;
+ unsigned char buf[bufsize] ;
+ USBtype_enum devType = (USBtype_enum)cwGetUSBType(deviceNo) ;
+
+ buf[0] = CUSBaccess::KeepCalm ;
+ buf[1] = minutes ;
+ buf[2] = minutes2restart ;
+ if (devType == AUTORESET_DEVICE || devType == WATCHDOG_DEVICE || devType == SWITCH1_DEVICE)
+ ok = SetValue(deviceNo, buf, 3) ;
+ else if (devType == CONTACT00_DEVICE || devType == SWITCHX_DEVICE || devType == WATCHDOGXP_DEVICE)
+ ok = SetValue(deviceNo, buf, bufsize) ;
+
+ return ok ;
+ }
+
+int
+CUSBaccess::GetTemperature(int deviceNo, double *Temperature, int *timeID) {
+ int ok = 1 ;
+ const int maxDevs = 128 ;
+ static double lastTemperature[maxDevs] ;
+ static int initialized = 0 ;
+
+ if (!initialized) {
+ for (int i=0 ; i < maxDevs ; i++)
+ lastTemperature[i] = -200. ;
+ initialized = 1 ;
+ }
+
+ switch ((USBtype_enum)cwGetUSBType(deviceNo)) {
+ case TEMPERATURE_DEVICE: {
+ const int bufSize = 6 ;
+ unsigned char buf[bufSize] ;
+ // read temperature
+ if (GetValue(deviceNo, buf, bufSize) == 0) {
+ ok = 0 ;
+ break ;
+ }
+ *timeID = ((buf[0] & 0x7f) << 8) + buf[1] ;
+ int value = (buf[2] << 5) + (buf[3] >> 3) ;
+ if (value & 0x1000) // negativ!
+ value = (value & 0xfff) - 0x1000 ;
+ int valid = (buf[0] & 0x80) ; // MSB = valid-bit
+ if (!valid) { // invalid time
+ ok = 0 ;
+ break ;
+ }
+ *Temperature = value * 0.0625 ;
+ break ;
+ }
+ case TEMPERATURE2_DEVICE: {
+ const int bufSize = 7 ;
+ unsigned char buf[bufSize] ;
+ // read temperature
+ if (GetValue(deviceNo, buf, bufSize) == 0) {
+ ok = 0 ;
+ break ;
+ }
+ *timeID = ((buf[0] & 0x7f) << 8) + buf[1] ;
+ int value = (buf[2] << 5) + (buf[3] >> 3) ;
+ if (value & 0x1000) // negativ!
+ value = (value & 0xfff) - 0x1000 ;
+ int valid = (buf[0] & 0x80) ; // MSB = valid-bit
+ if (!valid) { // invalid time
+ ok = 0 ;
+ break ;
+ }
+ *Temperature = value * 0.0625 ;
+ if (*Temperature <= -39.99 || *Temperature > 200.)
+ ok = 0 ; // can't happen!
+ break ;
+ }
+ case HUMIDITY1_DEVICE:
+ case TEMPERATURE5_DEVICE: {
+ const int bufSize = 7 ;
+ unsigned char buf[bufSize] ;
+ // read temperature
+ if (GetValue(deviceNo, buf, bufSize) == 0) {
+ ok = 0 ;
+ break ;
+ }
+
+ int version = cwGetVersion(deviceNo) ;
+
+ *timeID = ((buf[0] & 0x3f) << 8) + buf[1] ;
+ int humi = (buf[2] << 8) + buf[3] ;
+ int temp = (buf[4] << 8) + buf[5] ;
+ int valid = ((buf[0] & 0xc0) == 0xc0) ; // MSB = valid-bit
+ if (valid)
+ valid = ((buf[4] & 0x80) == 0) ; // MSB must be 0
+ if (valid)
+ valid = (buf[4] != 0) ; // if value is > 0x100 (temp=-37,5C) there must be an error
+ if (!valid) { // invalid time
+ ok = 0 ;
+ break ;
+ }
+ // double humidity = -4. + 0.0405 * humi - 2.8 * humi * humi / 1000000 ;
+ if (version < 5) // 14 bit
+ *Temperature = -40. + 0.01 * temp ;
+ else // 12 bit
+ *Temperature = -40. + 0.04 * temp ;
+ if (*Temperature <= -39.99 || *Temperature > 200.)
+ ok = 0 ; // can't happen!
+ break ;
+ }
+ default:
+ ok = 0 ;
+ break ;
+ }
+
+ if (ok && deviceNo < maxDevs) {
+ double t = lastTemperature[deviceNo] ;
+ if (t > -199.) {
+ if (*Temperature < t - 1. || *Temperature > t + 1.) // this should be measured twice
+#pragma message("das reicht nicht - Fehler tritt auch mit kleinen Differenzen auf (humi 21,4 = 0x5ff, vorher ca.0x615")
+ ok = 0 ;
+ }
+ lastTemperature[deviceNo] = *Temperature ;
+ }
+
+ return ok ;
+ }
+
+int
+CUSBaccess::GetHumidity(int deviceNo, double *Humidity, int *timeID) {
+ int ok = 1 ;
+
+ switch (cwGetUSBType(deviceNo)) {
+ case HUMIDITY1_DEVICE: {
+ const int bufSize = 7 ;
+ unsigned char buf[bufSize] ;
+ // read temperature
+ if (GetValue(deviceNo, buf, bufSize) == 0) {
+ ok = 0 ;
+ break ;
+ }
+
+ int version = cwGetVersion(deviceNo) ;
+
+ *timeID = ((buf[0] & 0x3f) << 8) + buf[1] ;
+ int humi = (buf[2] << 8) + buf[3] ;
+ int valid = ((buf[0] & 0xc0) == 0xc0) ; // MSB = valid-bit
+ if (valid)
+ valid = ((buf[2] & 0x80) == 0) ; // MSB must be 0
+ if (!valid) { // invalid time
+ ok = 0 ;
+ break ;
+ }
+ // *Temperature = -40. + 0.01 * temp ;
+ if (version < 5) // 12 bit
+ *Humidity = -4. + 0.0405 * humi - 2.8 * humi * humi / 1000000 ;
+ else // 8 bit
+ *Humidity = -4. + 0.648 * humi - 7.2 * humi * humi / 10000 ;
+ if (*Humidity < 0.)
+ ok = 0 ; // this is not possible!!
+ break ;
+ }
+ default:
+ ok = 0 ;
+ break ;
+ }
+ return ok ;
+ }
+
+
+int // return 0 for pre 2014 designed devices, 13 for new devices
+CUSBaccess::GetHWversion(int deviceNo) {
+ int rval = cwGetHWversion(deviceNo) ;
+
+ return rval ;
+ }
+
+// returns data if ok or -1 in case of an error
+int
+CUSBaccess::IOX(int deviceNo, int addr, int data) {
+ int rval = cwIOX(deviceNo, addr, data) ;
+
+ return rval ;
+ }
+
+
+void
+CUSBaccess::DebugWrite(char *s) {
+ cwDebugWrite(s) ;
+ }
+
+void
+CUSBaccess::DebugWrite(char *f, int a1) {
+ static char s[1024] ;
+ sprintf(s, f, a1) ;
+ cwDebugWrite(s) ;
+ }
+
+void
+CUSBaccess::DebugWrite(char *f, int a1,int a2) {
+ static char s[1024] ;
+ sprintf(s, f, a1, a2) ;
+ cwDebugWrite(s) ;
+ }
+
+void
+CUSBaccess::DebugWrite(char *f, int a1, int a2, int a3) {
+ static char s[1024] ;
+ sprintf(s, f, a1, a2, a3) ;
+ cwDebugWrite(s) ;
+ }
+
+void
+CUSBaccess::DebugWrite(char *f, int a1, int a2, int a3, int a4) {
+ static char s[1024] ;
+ sprintf(s, f, a1, a2, a3, a4) ;
+ cwDebugWrite(s) ;
+ }
diff --git a/USBaccess.h b/USBaccess.h
new file mode 100644
index 0000000..7fd51a1
--- /dev/null
+++ b/USBaccess.h
@@ -0,0 +1,131 @@
+// DLL class definitions for access to USB HID devices
+//
+// (C) 2001-2014 Copyright Cleware GmbH
+// All rights reserved
+//
+// History:
+// 05.01.2001 ws Initial coding
+// 17.07.2001 ws cleanup interface
+// 10.12.2001 ws cleanup interface again, basic class to hide implementation details
+// 13.12.2001 ws introduced versionNumber and virtual destructor
+// 23.05.2002 ws added switch access
+// ...
+// 03.02.2003 ws added switch version 10
+// 04.08.2003 ws added humidity
+// 21.01.2004 ws fixed some humidity problems
+// 2004 ws added contact + io16
+// 05.02.2005 ws added ADC08-Support
+// 25.05.13 ws new controller support
+// 15.05.2014 ws 4.3.0 added new controller support
+
+
+
+// The following ifdef block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the USBACCESS_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// USBACCESS_API functions as being imported from a DLL, wheras this DLL sees symbols
+// defined with this macro as being exported.
+
+
+#ifndef __USBACCESS_H__
+#define __USBACCESS_H__
+
+#ifdef __APPLE__
+#include "mac-hidapi/hidapi.h"
+#else
+#include <hidapi/hidapi.h>
+#endif
+
+typedef hid_device * HANDLE;
+
+const int USBaccessVersion = 330 ;
+
+class CUSBaccess {
+ public:
+ enum USBactions { LEDs=0, EEwrite=1, EEread=2, Reset=3, KeepCalm=4, GetInfo=5,
+ StartMeasuring=6, // USB-Humidity
+ Configure=7, // USB-IO16-V10, USB-Counter-V05
+ RunPoint=10 // USB-Encoder
+ } ;
+ enum USBInfoType { OnlineTime=1, OnlineCount=2, ManualTime=3, ManualCount=4 } ;
+ enum LED_IDs { LED_0=0, LED_1=1, LED_2=2, LED_3=3 } ;
+ enum COUNTER_IDs { COUNTER_0=0, COUNTER_1=1 } ;
+ enum SWITCH_IDs { SWITCH_0=0x10, SWITCH_1=0x11, SWITCH_2=0x12, SWITCH_3=0x13,
+ SWITCH_4=0x14, SWITCH_5=0x15, SWITCH_6=0x16, SWITCH_7=0x17,
+ SWITCH_8=0x18, SWITCH_9=0x19, SWITCH_10=0x1a, SWITCH_11=0x1b,
+ SWITCH_12=0x1c, SWITCH_13=0x1d, SWITCH_14=0x1e, SWITCH_15=0x1f
+ } ;
+ enum USBtype_enum { ILLEGAL_DEVICE=0,
+ LED_DEVICE=0x01,
+ POWER_DEVICE=0x02,
+ WATCHDOG_DEVICE=0x05,
+ AUTORESET_DEVICE=0x06,
+ WATCHDOGXP_DEVICE=0x07,
+ SWITCH1_DEVICE=0x08,
+ SWITCH2_DEVICE=0x09, SWITCH3_DEVICE=0x0a, SWITCH4_DEVICE=0x0b,
+ SWITCH5_DEVICE=0x0c, SWITCH6_DEVICE=0x0d, SWITCH7_DEVICE=0x0e, SWITCH8_DEVICE=0x0f,
+ TEMPERATURE_DEVICE=0x10,
+ TEMPERATURE2_DEVICE=0x11,
+ TEMPERATURE5_DEVICE=0x15,
+ HUMIDITY1_DEVICE=0x20,
+ SWITCHX_DEVICE=0x28, // new switch 3,4,8
+ CONTACT00_DEVICE=0x30, CONTACT01_DEVICE=0x31, CONTACT02_DEVICE=0x32, CONTACT03_DEVICE=0x33,
+ CONTACT04_DEVICE=0x34, CONTACT05_DEVICE=0x35, CONTACT06_DEVICE=0x36, CONTACT07_DEVICE=0x37,
+ CONTACT08_DEVICE=0x38, CONTACT09_DEVICE=0x39, CONTACT10_DEVICE=0x3a, CONTACT11_DEVICE=0x3b,
+ CONTACT12_DEVICE=0x3c, CONTACT13_DEVICE=0x3d, CONTACT14_DEVICE=0x3e, CONTACT15_DEVICE=0x3f,
+ F4_DEVICE=0x40,
+ KEYC01_DEVICE=0x41, KEYC16_DEVICE=0x42,
+ ADC0800_DEVICE=0x50, ADC0801_DEVICE=0x51, ADC0802_DEVICE=0x52, ADC0803_DEVICE=0x53,
+ COUNTER00_DEVICE=0x60,
+ ENCODER01_DEVICE=0x80,
+ BUTTON_NODEVICE=0x1000
+ } ;
+ private:
+ class CUSBaccessBasic * X ; // avoid export of internal USB variables
+
+ public:
+ CUSBaccess() ;
+ virtual ~CUSBaccess() ; // maybe used as base class
+
+ virtual int OpenCleware() ; // returns number of found Cleware devices
+ virtual int CloseCleware() ; // close all Cleware devices
+ virtual int Recover(int devNum) ; // try to find disconnected devices, returns true if succeeded
+ virtual HANDLE GetHandle(int deviceNo) ;
+ virtual int GetValue(int deviceNo, unsigned char *buf, int bufsize) ;
+ virtual int SetValue(int deviceNo, unsigned char *buf, int bufsize) ;
+ virtual int SetLED(int deviceNo, enum LED_IDs Led, int value) ; // value: 0=off 7=medium 15=highlight
+ virtual int SetSwitch(int deviceNo, enum SWITCH_IDs Switch, int On) ; // On: 0=off, 1=on
+ virtual int GetSwitch(int deviceNo, enum SWITCH_IDs Switch) ; // On: 0=off, 1=on, -1=error
+ virtual int GetSeqSwitch(int deviceNo, enum SWITCH_IDs Switch, int seqNum) ; // On: 0=off, 1=on, -1=error
+ virtual int GetSwitchConfig(int deviceNo, int *switchCount, int *buttonAvailable) ;
+ virtual int GetTemperature(int deviceNo, double *Temperature, int *timeID) ;
+ virtual int GetHumidity(int deviceNo, double *Humidity, int *timeID) ;
+ virtual int ResetDevice(int deviceNo) ;
+ virtual int StartDevice(int deviceNo) ;
+ virtual int CalmWatchdog(int deviceNo, int minutes, int minutes2restart) ;
+ virtual int GetVersion(int deviceNo) ;
+ virtual int GetUSBType(int deviceNo) ;
+ virtual int GetSerialNumber(int deviceNo) ;
+ virtual int GetDLLVersion() { return USBaccessVersion ; }
+ virtual int GetManualOnCount(int deviceNo) ; // returns how often switch is manually turned on
+ virtual int GetManualOnTime(int deviceNo) ; // returns how long (seconds) switch is manually turned on
+ virtual int GetOnlineOnCount(int deviceNo) ; // returns how often switch is turned on by USB command
+ virtual int GetOnlineOnTime(int deviceNo) ; // returns how long (seconds) switch is turned on by USB command
+ virtual int GetMultiSwitch(int deviceNo, unsigned long int *mask, unsigned long int *value, int seqNumber) ;
+ virtual int SetMultiSwitch(int deviceNo, unsigned long int value) ;
+ virtual int SetMultiConfig(int deviceNo, unsigned long int directions) ;
+ virtual int GetCounter(int deviceNo, enum COUNTER_IDs counterID) ; // COUNTER_IDs ununsed until now
+ virtual int SetCounter(int deviceNo, int counter, enum COUNTER_IDs counterID) ; // -1=error, COUNTER_IDs ununsed until now
+ virtual int SyncDevice(int deviceNo, unsigned long int mask) ;
+ virtual int GetHWversion(int deviceNo) ; // return HWversion (0 for pre 2014 designed devices, 13 for new devices)
+ virtual int IOX(int deviceNo, int addr, int data) ; // for internal use only, wrong usage may destroy device
+ virtual void DebugWrite(char *s) ;
+ virtual void DebugWrite(char *f, int a1) ;
+ virtual void DebugWrite(char *f, int a1, int a2) ;
+ virtual void DebugWrite(char *f, int a1, int a2, int a3) ;
+ virtual void DebugWrite(char *f, int a1, int a2, int a3, int a4) ;
+ virtual void Sleep(int ms) { usleep(ms * 1000) ; } // for Linux
+ } ;
+
+#endif // __USBACCESS_H__
diff --git a/USBaccessBasic.cpp b/USBaccessBasic.cpp
new file mode 100644
index 0000000..2785009
--- /dev/null
+++ b/USBaccessBasic.cpp
@@ -0,0 +1,521 @@
+// Basic class implementation for access to USB HID devices
+//
+// (C) 2001 Copyright Cleware GmbH
+// All rights reserved
+//
+// Converted to HidApi by folkert van Heusden, mail@vanheusden.com
+//
+// History:
+// 05.01.01 ws Initial coding
+// 01.11.01 ws Linux coding
+// 30.10.12 fvh libusb version
+
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "USBaccessBasic.h"
+
+#define TIMEOUT 1000
+
+const int maxHID = 256 ;
+SUSBdata data[256] ;
+
+int nr = 0;
+
+void cwInitCleware()
+{
+ hid_init();
+}
+
+void cwCloseCleware()
+{
+ for(int h=0; h < maxHID; h++)
+ {
+ if (data[h].handle)
+ {
+ hid_close(data[h].handle);
+
+ data[h].handle = NULL;
+ }
+ }
+
+ hid_exit();
+}
+
+int
+cwIOX(int deviceNo, int addr, int datum) { // return datum if ok, datum=-1=Read operation
+ const int maxbufsize = 8 ;
+ int bufsize = 6 ;
+ unsigned char buf[maxbufsize] ;
+ int ok = 1 ;
+ if (deviceNo < 0 || deviceNo >= maxHID || data[deviceNo].handle == NULL)
+ return-1 ;
+
+ int devType = data[deviceNo].gadgettype ;
+ int version = data[deviceNo].gadgetVersionNo ;
+ int sixteenbit = (devType == TEMPERATURE2_DEVICE || devType == HUMIDITY1_DEVICE || devType == HUMIDITY2_DEVICE) ;
+
+ if (datum >= 0) { // -1 = Read command
+ buf[0] = EEwrite ;
+ if (sixteenbit) {
+ buf[1] = addr >> 8 ; // high byte 0
+ buf[2] = addr ;
+ buf[3] = datum ;
+ cwSetValue(deviceNo, buf, 4) ;
+ }
+ else if (devType == CONTACT00_DEVICE && version > 6) {
+ buf[1] = addr ;
+ buf[2] = datum ;
+ cwSetValue(deviceNo, buf, 5) ;
+ }
+ else if (devType == DISPLAY_DEVICE) {
+ buf[1] = addr ;
+ buf[2] = datum ;
+ cwSetValue(deviceNo, buf, 5) ;
+ }
+ else if (devType == WATCHDOGXP_DEVICE || devType == SWITCHX_DEVICE) {
+ buf[1] = addr ;
+ buf[2] = datum ;
+ cwSetValue(deviceNo, buf, 5) ;
+ }
+ else if (devType == ENCODER01_DEVICE) {
+ buf[1] = addr ;
+ buf[2] = datum ;
+ cwSetValue(deviceNo, buf, 6) ;
+ }
+ else if (devType == ADC0800_DEVICE) {
+ buf[1] = addr ;
+ buf[2] = datum ;
+ cwSetValue(deviceNo, buf, 3) ;
+ }
+ else if (devType == POWER_DEVICE) {
+ buf[1] = addr ;
+ buf[2] = datum ;
+ cwSetValue(deviceNo, buf, 3) ;
+ }
+ else if (devType == KEYC16_DEVICE || devType == KEYC01_DEVICE) {
+ buf[1] = addr ;
+ buf[2] = datum ;
+ cwSetValue(deviceNo, buf, 5) ;
+ }
+ else if (devType == MOUSE_DEVICE) {
+ buf[1] = addr ;
+ buf[2] = datum ;
+ cwSetValue(deviceNo, buf, 5) ;
+ }
+ else {
+ buf[1] = addr ;
+ buf[2] = datum ;
+ cwSetValue(deviceNo, buf, 3) ;
+ }
+ usleep(100*1000) ;
+ }
+
+ buf[0] = EEread ;
+ if (sixteenbit) {
+ buf[1] = 0 ; // high byte 0
+ buf[2] = addr ;
+ buf[3] = 0 ;
+ cwSetValue(deviceNo, buf, 4) ;
+ bufsize = 7 ;
+ }
+ else if (devType == CONTACT00_DEVICE && version > 6) {
+ buf[1] = addr ;
+ buf[2] = 0 ;
+ cwSetValue(deviceNo, buf, 5) ;
+ }
+ else if (devType == DISPLAY_DEVICE) {
+ buf[1] = addr ;
+ buf[2] = 0 ;
+ cwSetValue(deviceNo, buf, 5) ;
+ }
+ else if (devType == WATCHDOGXP_DEVICE || devType == SWITCHX_DEVICE) {
+ buf[1] = addr ;
+ buf[2] = 0 ;
+ cwSetValue(deviceNo, buf, 5) ;
+ }
+ else if (devType == KEYC16_DEVICE || devType == KEYC01_DEVICE) {
+ buf[1] = addr ;
+ buf[2] = 0 ;
+ cwSetValue(deviceNo, buf, 5) ;
+ bufsize = 8 ;
+ }
+ else if (devType == MOUSE_DEVICE) {
+ buf[1] = addr ;
+ buf[2] = 0 ;
+ cwSetValue(deviceNo, buf, 5) ;
+ bufsize = 4 ;
+ }
+ else if (devType == ADC0800_DEVICE) {
+ buf[1] = addr ;
+ buf[2] = 0 ;
+ cwSetValue(deviceNo, buf, 3) ;
+ bufsize = 4 ;
+ }
+ else if (devType == POWER_DEVICE) {
+ buf[1] = addr ;
+ buf[2] = 0 ;
+ cwSetValue(deviceNo, buf, 3) ;
+ bufsize = 3 ;
+ }
+ else if (devType == ENCODER01_DEVICE) {
+ buf[1] = addr ;
+ buf[2] = 0 ;
+ cwSetValue(deviceNo, buf, 6) ;
+ }
+ else {
+ buf[1] = addr ;
+ buf[2] = 0 ;
+ cwSetValue(deviceNo, buf, 3) ;
+ }
+
+ usleep(10*1000) ;
+ ok = 40 ;
+ int Xdata = -1 ;
+ while (ok) {
+ if (cwGetValue(deviceNo, buf, bufsize)) {
+ if ((buf[0] & 0x80) == 0) {
+ if (--ok == 0) {
+ // MessageBox("GetValue still not valid", "Error") ;
+ break ;
+ }
+ else {
+ usleep(10*1000) ;
+ continue ;
+ }
+ }
+ int Xaddr = 0 ;
+ if (bufsize == 3 || devType == MOUSE_DEVICE) {
+ Xaddr = buf[1] ;
+ Xdata = buf[2] ;
+ }
+ else if (bufsize == 4) {
+ Xaddr = buf[2] ;
+ Xdata = buf[3] ;
+ }
+ else {
+ Xaddr = buf[4] ;
+ Xdata = buf[5] ;
+ }
+ if (sixteenbit) {
+ Xaddr = (Xaddr << 8) + buf[5] ;
+ Xdata = buf[6] ;
+ }
+ if (Xaddr != addr) {
+ if (--ok == 0) {
+ // MessageBox("GetValue address error", "Error") ;
+ break ;
+ }
+ else {
+ usleep(10*1000) ;
+ continue ;
+ }
+ }
+ if (datum >= 0 && Xdata != datum) {
+ if (--ok == 0) {
+ // MessageBox("Write error", "Error") ;
+ break ;
+ }
+ else {
+ usleep(10*1000) ;
+ continue ;
+ }
+ }
+ break ;
+ }
+ else {
+ if (--ok == 0) {
+ // MessageBox("GetValue failed", "Error") ;
+ break ;
+ }
+ else {
+ usleep(10*1000) ;
+ continue ;
+ }
+ }
+ break ; // read was ok
+ }
+ if (!ok)
+ Xdata = -1 ;
+
+ return Xdata ;
+ }
+
+// returns number of found Cleware devices
+int cwOpenCleware(const char *path = NULL)
+{
+ int n = 0;
+ struct hid_device_info *devs = NULL, *cur_dev = NULL;
+
+ memset(&data, 0x00, sizeof data);
+
+ cur_dev = devs = hid_enumerate(0x0d50, 0x0);
+
+ while (cur_dev)
+ {
+ data[n].v = cur_dev->vendor_id;
+ data[n].p = cur_dev->product_id;
+ data[n].hidpath = strdup(cur_dev->path);
+
+ data[n].gadgettype = (enum USBtype_enum)data[n].p;
+ data[n].gadgetVersionNo = cur_dev -> release_number;
+
+ char buffer[256] = { 0 };
+ wcstombs(buffer, cur_dev->serial_number, wcslen(cur_dev->serial_number));
+
+ data[n].SerialNumber = strtol(buffer, NULL, 16);
+ data[n].report_type = 123; // HID_REPORT_ID_FIRST; // NOT USED *FVH*
+ if (data[n].SerialNumber == 0x63813) { // this is the next controller - get serial number directly
+ data[n].HWversion = 13 ;
+ data[n].SerialNumber = -1 ;
+ }
+ if (data[n].SerialNumber <= 0) { // getting the Serial number failed, so get it directly!
+ data[n].handle = hid_open_path(data[n].hidpath);
+ int SerNum = 0 ;
+ int addr = 0;
+ for (addr=8 ; addr <= 14 ; addr++) { // unicode byte 2 == 0
+ int data = cwIOX(n, addr, -1) ;
+ if (data >= '0' && data <= '9')
+ SerNum = SerNum * 16 + data - '0' ;
+ else if (data >= 'A' && data <= 'F')
+ SerNum = SerNum * 16 + data - 'A' + 10 ;
+ else {
+ SerNum = -1 ; // failed!
+ break ;
+ }
+ }
+ data[n].SerialNumber = SerNum ;
+ hid_close(data[n].handle);
+ data[n].handle = NULL;
+ }
+
+ n++;
+ cur_dev = cur_dev->next;
+ }
+
+ hid_free_enumeration(devs);
+
+ return n;
+}
+
+int cwOpenDevice(int index)
+{
+ if (data[index].handle)
+ return 1;
+
+ data[index].handle = hid_open_path(data[index].hidpath);
+
+ char ok = data[index].handle != NULL;
+
+ if (!ok)
+ fprintf(stderr, "Failed to open %04x:%04x (%d)\n", data[index].v, data[index].p, data[index].SerialNumber);
+
+ return ok;
+}
+
+int cwCloseDevice(int index)
+{
+ if (data[index].handle)
+ {
+ hid_close(data[index].handle);
+
+ data[index].handle = NULL;
+ }
+
+ return 1;
+}
+
+int cwRecover(int devNo)
+{
+ if (data[devNo].handle == NULL)
+ return 0;
+
+ return 1;
+}
+
+void fail(const char *msg, hid_device *handle)
+{
+ const wchar_t *wstr = hid_error(handle);
+
+ if (!wstr)
+ {
+ if (errno)
+ printf("%s: %s\n", msg, strerror(errno));
+ else
+ printf("%s\n", msg);
+ }
+ else
+ {
+ int len = wcslen(wstr);
+ char* ascii = new char[len + 1];
+
+ wcstombs(ascii, wstr, len);
+
+ printf("%s: %s\n", msg, ascii);
+
+ delete [] ascii;
+ }
+}
+
+int cwGetValue(int deviceNo, unsigned char *buf, int bufsize)
+{
+ if (!cwOpenDevice(deviceNo))
+ return 0;
+
+ if (data[deviceNo].handle == NULL)
+ return 0;
+
+ unsigned char lbuf[3] = { 0x00, (unsigned char)(nr++), 0x81 };
+ if (hid_send_feature_report(data[deviceNo].handle, lbuf, sizeof lbuf) < 0)
+ {
+ fail("cwGetValue::hid_write() failed", data[deviceNo].handle);
+
+ return 0;
+ }
+
+ if (hid_read(data[deviceNo].handle, buf, bufsize) < 0)
+ {
+ fail("cwGetValue::hid_read() failed", data[deviceNo].handle);
+
+ return 0;
+ }
+
+ return 1;
+}
+
+int cwSetValue(int deviceNo, unsigned char *buf, int bufsize)
+{
+ if (!cwOpenDevice(deviceNo))
+ return 0;
+
+ if (data[deviceNo].handle == NULL)
+ return 0;
+
+ char *b = new char[bufsize + 1];
+ memcpy(b + 1, buf, bufsize);
+ b[0] = 0x00;
+
+//#ifdef macos
+#if 1
+ if (hid_write(data[deviceNo].handle, (unsigned char *)b, bufsize + 1) < 0)
+#else
+ if (hid_send_feature_report(data[deviceNo].handle, (unsigned char *)b, bufsize + 1) < 0)
+#endif
+ {
+ fail("cwSetValue::hid_write() failed", data[deviceNo].handle);
+
+ delete [] b;
+
+ return 0;
+ }
+
+ delete [] b;
+
+ return 1;
+}
+
+hid_device * cwGetHandle(int deviceNo)
+{
+ if (!cwOpenDevice(deviceNo))
+ return 0;
+
+ return data[deviceNo].handle;
+}
+
+int cwGetVersion(int deviceNo)
+{
+ return data[deviceNo].gadgetVersionNo;
+}
+
+int cwGetSerialNumber(int deviceNo)
+{
+ return data[deviceNo].SerialNumber;
+}
+
+enum USBtype_enum cwGetUSBType(int deviceNo)
+{
+ return data[deviceNo].gadgettype;
+}
+
+int
+cwValidSerNum(int SerialNumber, enum USBtype_enum devType) {
+ static int outdated[] = {
+ 54,59,60,62,63,64,65,66,67,68,69,
+ 72,74,75,76,77,82,83,85,87,88,89,
+ 90,91,92,93,95,96,98,99,
+ 100,101,102,103,105,106,107,108,109,110,
+ 113,116,117,119,120,122,124,125,126,128,
+ 131,132,135,139,140,142,143,145,147,148,149,
+ 150,151,152,153,154,155,156,157,160,161,162,163,168,169,
+ 170,171,172,173,174,175,176,180,184,187,188,189,190,191,192,193,195,197,198,
+ 201,203,204, 205, 206, 219,220,221,260,272,273,274,275,276,278,279,
+ 280,281,416,
+ 5002,5003,5004,5005,5006,5007,5008,5010,
+ 5011,5012,5013,5014,5015,5016,
+ 5017,5018,5019,5020,5021,5022,5023,5024,
+ 5025,5026,5028,5029,5032,5033,5034,
+ 5035,5036,5041,5043,5044,5046,5049,5050,
+ 5052,5053,5055,5057,5071,5073,5076,5089,5091,5101,5102,5103,
+ 5104,5106,5109,5114,5116,5117,5118,5119,
+ 5120,5121,5122,5147,5163,5164,7502,7503,
+ 7504,7505,7511,7513,8192,8193,8194,
+ 8503,8504,8505,8506,8507,8508,8509,8510,8511,8512,8513
+ } ;
+
+ static int outdatedSwitches[] = { // double numbers!!
+ 510,511,513,514,517,518,520,532 // Switches
+// , 5314 // test
+ } ;
+
+ int rval = 1 ;
+
+ int size = sizeof(outdated) / sizeof(int) ;
+ int *pt = &(outdated[0]) ;
+ int i ;
+
+ for (i=0 ; i < size ; i++, pt++) {
+ if (SerialNumber == *pt) {
+ rval = 0 ;
+ break ;
+ }
+ }
+ if (rval == 1 && devType == SWITCH1_DEVICE) {
+ size = sizeof(outdatedSwitches) / sizeof(int) ;
+ pt = &(outdatedSwitches[0]) ;
+ for (i=0 ; i < size ; i++, pt++) {
+ if (SerialNumber == *pt) {
+ rval = 0 ;
+ break ;
+ }
+ }
+ }
+
+ return rval ;
+ }
+
+void
+cwDebugWrite(char *s) {
+ fputs(s, stderr) ;
+ }
+
+void
+cwDebugClose() {
+ }
+
+int
+cwGetHWversion(int deviceNo) { // return current
+ int rval = 0 ;
+
+ if (deviceNo < 0 || deviceNo >= maxHID || data[deviceNo].handle == NULL)
+ rval = -1 ;
+ else
+ rval = data[deviceNo].HWversion ;
+
+ return rval ;
+ }
diff --git a/USBaccessBasic.h b/USBaccessBasic.h
new file mode 100644
index 0000000..629995c
--- /dev/null
+++ b/USBaccessBasic.h
@@ -0,0 +1,87 @@
+// Basic class definitions for access to USB HID devices
+//
+// (C) 2001 Copyright Cleware GmbH
+// All rights reserved
+//
+// History:
+// 05.01.01 ws Initial coding
+// 17.07.01 ws cleanup interface
+// 03.11.02 ws small changes for Linux
+
+
+#ifndef __USBACCESSBASIC_H__
+#define __USBACCESSBASIC_H__
+
+#ifdef __APPLE__
+#include "mac-hidapi/hidapi.h"
+#else
+#include <hidapi/hidapi.h>
+#endif
+
+typedef hid_device * HANDLE;
+
+enum USBtype_enum { ILLEGAL_DEVICE=0,
+ LED_DEVICE=0x01,
+ POWER_DEVICE=0x02,
+ DISPLAY_DEVICE=0x03,
+ WATCHDOG_DEVICE=0x05,
+ AUTORESET_DEVICE=0x06,
+ WATCHDOGXP_DEVICE=0x07,
+ SWITCH1_DEVICE=0x08,
+ SWITCH2_DEVICE=0x09, SWITCH3_DEVICE=0x0a, SWITCH4_DEVICE=0x0b,
+ SWITCH5_DEVICE=0x0c, SWITCH6_DEVICE=0x0d, SWITCH7_DEVICE=0x0e, SWITCH8_DEVICE=0x0f,
+ TEMPERATURE_DEVICE=0x10,
+ TEMPERATURE2_DEVICE=0x11,
+ TEMPERATURE5_DEVICE=0x15,
+ HUMIDITY1_DEVICE=0x20,HUMIDITY2_DEVICE=0x21,
+ SWITCHX_DEVICE=0x28, // new switch 3,4,8
+ // CONTACT1_DEVICE=0x30
+ CONTACT00_DEVICE=0x30, CONTACT01_DEVICE=0x31, CONTACT02_DEVICE=0x32, CONTACT03_DEVICE=0x33,
+ CONTACT04_DEVICE=0x34, CONTACT05_DEVICE=0x35, CONTACT06_DEVICE=0x36, CONTACT07_DEVICE=0x37,
+ CONTACT08_DEVICE=0x38, CONTACT09_DEVICE=0x39, CONTACT10_DEVICE=0x3a, CONTACT11_DEVICE=0x3b,
+ CONTACT12_DEVICE=0x3c, CONTACT13_DEVICE=0x3d, CONTACT14_DEVICE=0x3e, CONTACT15_DEVICE=0x3f,
+ F4_DEVICE=0x40,
+ KEYC01_DEVICE=0x41, KEYC16_DEVICE=0x42,MOUSE_DEVICE=0x43,
+ ADC0800_DEVICE=0x50, ADC0801_DEVICE=0x51, ADC0802_DEVICE=0x52, ADC0803_DEVICE=0x53,
+ COUNTER00_DEVICE=0x60,
+ ENCODER01_DEVICE=0x80,
+ BUTTON_NODEVICE=0x1000
+ } ;
+enum USBactions { LEDs=0, EEwrite=1, EEread=2, Reset=3, KeepCalm=4, GetInfo=5,
+ StartMeasuring=6, // USB-Humidity
+ Configure=7, // USB-IO16-V10, USB-Counter-V05
+ Display=8, // USB/Display
+ RunPoint=10, // USB-Encoder
+ Programm=15 // Transfer new Firmware (internal use only)
+ } ;
+
+typedef struct {
+ unsigned short v, p;
+ hid_device *handle;
+ int gadgetVersionNo;
+ enum USBtype_enum gadgettype;
+ int SerialNumber;
+ int report_type;
+ int HWversion ;
+ char *hidpath;
+ } SUSBdata;
+
+extern int nr;
+
+void cwInitCleware();
+int cwOpenCleware(const char *path); // returns number of found Cleware devices
+int cwRecover(int devNo);
+void cwCloseCleware();
+int cwGetValue(int deviceNo, unsigned char *buf, int bufsize);
+int cwSetValue(int deviceNo, unsigned char *buf, int bufsize);
+hid_device * cwGetHandle(int deviceNo);
+int cwGetVersion(int deviceNo);
+int cwGetSerialNumber(int deviceNo);
+enum USBtype_enum cwGetUSBType(int deviceNo);
+int cwValidSerNum(int SerialNumber, enum USBtype_enum devType) ;
+void cwDebugWrite(char *s) ;
+void cwDebugClose() ;
+int cwGetHWversion(int deviceNo);
+int cwIOX(int deviceNo, int addr, int data) ;
+
+#endif // __USBACCESS_H__
diff --git a/circle.yml b/circle.yml
new file mode 100644
index 0000000..1ec501c
--- /dev/null
+++ b/circle.yml
@@ -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
index 0000000..76ded4b
--- /dev/null
+++ b/cleware.i
@@ -0,0 +1,252 @@
+%module cleware
+%{
+typedef int HANDLE ;
+
+const int USBaccessVersion = 330 ;
+
+#define CLEWARE_DEBUG 1
+
+#define INVALID_HANDLE_VALUE -1
+
+enum USBtype_enum { ILLEGAL_DEVICE=0,
+ LED_DEVICE=0x01,
+ POWER_DEVICE=0x02,
+ DISPLAY_DEVICE=0x03,
+ WATCHDOG_DEVICE=0x05,
+ AUTORESET_DEVICE=0x06,
+ WATCHDOGXP_DEVICE=0x07,
+ SWITCH1_DEVICE=0x08,
+ SWITCH2_DEVICE=0x09, SWITCH3_DEVICE=0x0a, SWITCH4_DEVICE=0x0b,
+ SWITCH5_DEVICE=0x0c, SWITCH6_DEVICE=0x0d, SWITCH7_DEVICE=0x0e, SWITCH8_DEVICE=0x0f,
+ TEMPERATURE_DEVICE=0x10,
+ TEMPERATURE2_DEVICE=0x11,
+ TEMPERATURE5_DEVICE=0x15,
+ HUMIDITY1_DEVICE=0x20,HUMIDITY2_DEVICE=0x21,
+ SWITCHX_DEVICE=0x28, // new switch 3,4,8
+ // CONTACT1_DEVICE=0x30
+ CONTACT00_DEVICE=0x30, CONTACT01_DEVICE=0x31, CONTACT02_DEVICE=0x32, CONTACT03_DEVICE=0x33,
+ CONTACT04_DEVICE=0x34, CONTACT05_DEVICE=0x35, CONTACT06_DEVICE=0x36, CONTACT07_DEVICE=0x37,
+ CONTACT08_DEVICE=0x38, CONTACT09_DEVICE=0x39, CONTACT10_DEVICE=0x3a, CONTACT11_DEVICE=0x3b,
+ CONTACT12_DEVICE=0x3c, CONTACT13_DEVICE=0x3d, CONTACT14_DEVICE=0x3e, CONTACT15_DEVICE=0x3f,
+ F4_DEVICE=0x40,
+ KEYC01_DEVICE=0x41, KEYC16_DEVICE=0x42,MOUSE_DEVICE=0x43,
+ ADC0800_DEVICE=0x50, ADC0801_DEVICE=0x51, ADC0802_DEVICE=0x52, ADC0803_DEVICE=0x53,
+ COUNTER00_DEVICE=0x60,
+ ENCODER01_DEVICE=0x80,
+ BUTTON_NODEVICE=0x1000
+ } ;
+enum USBactions { LEDs=0, EEwrite=1, EEread=2, Reset=3, KeepCalm=4, GetInfo=5,
+ StartMeasuring=6, // USB-Humidity
+ Configure=7, // USB-IO16-V10, USB-Counter-V05
+ Display=8, // USB/Display
+ RunPoint=10, // USB-Encoder
+ Programm=15 // Transfer new Firmware (internal use only)
+ } ;
+
+// 03.11.02 ws small changes for Linux
+typedef struct {
+ unsigned long int handle ;
+ int gadgetVersionNo ;
+ enum USBtype_enum gadgettype ;
+ int SerialNumber ;
+ int report_type ;
+ int HWversion ;
+ } cwSUSBdata ;
+
+
+void cwInitCleware() ;
+int cwOpenCleware() ; // returns number of found Cleware devices
+void cwCloseCleware() ;
+int cwGetValue(int deviceNo, int UsagePage, int Usage, unsigned char *buf, int bufsize) ;
+int cwSetValue(int deviceNo, int UsagePage, int Usage, unsigned char *buf, int bufsize) ;
+unsigned long int cwGetHandle(int deviceNo) ;
+int cwGetVersion(int deviceNo) ;
+enum USBtype_enum cwGetUSBType(int deviceNo) ;
+int cwGetSerialNumber(int deviceNo) ;
+int cwRecover(int devNum) ; // try to find disconnected devices
+int cwValidSerNum(int SerialNumber, enum USBtype_enum devType) ;
+int cwGetHWversion(int deviceNo) ; // return current
+int cwIOX(int deviceNo, int addr, int data) ;
+void cwDebugWrite(char *s) ;
+void cwDebugClose() ;
+
+class CUSBaccess {
+ public:
+ enum USBactions { LEDs=0, EEwrite=1, EEread=2, Reset=3, KeepCalm=4, GetInfo=5,
+ StartMeasuring=6, // USB-Humidity
+ Configure=7, // USB-IO16-V10, USB-Counter-V05
+ RunPoint=10, // USB-Encoder
+ ContactWrite=11, // 613er IO16
+ ContactRead=12 // 613er IO16
+ } ;
+ enum USBInfoType { OnlineTime=1, OnlineCount=2, ManualTime=3, ManualCount=4 } ;
+ enum LED_IDs { LED_0=0, LED_1=1, LED_2=2, LED_3=3 } ;
+ enum COUNTER_IDs { COUNTER_0=0, COUNTER_1=1 } ;
+ enum SWITCH_IDs { SWITCH_0=0x10, SWITCH_1=0x11, SWITCH_2=0x12, SWITCH_3=0x13,
+ SWITCH_4=0x14, SWITCH_5=0x15, SWITCH_6=0x16, SWITCH_7=0x17,
+ SWITCH_8=0x18, SWITCH_9=0x19, SWITCH_10=0x1a, SWITCH_11=0x1b,
+ SWITCH_12=0x1c, SWITCH_13=0x1d, SWITCH_14=0x1e, SWITCH_15=0x1f
+ } ;
+ enum USBtype_enum { ILLEGAL_DEVICE=0,
+ LED_DEVICE=0x01,
+ POWER_DEVICE=0x02,
+ WATCHDOG_DEVICE=0x05,
+ AUTORESET_DEVICE=0x06,
+ WATCHDOGXP_DEVICE=0x07,
+ SWITCH1_DEVICE=0x08,
+ SWITCH2_DEVICE=0x09, SWITCH3_DEVICE=0x0a, SWITCH4_DEVICE=0x0b,
+ SWITCH5_DEVICE=0x0c, SWITCH6_DEVICE=0x0d, SWITCH7_DEVICE=0x0e, SWITCH8_DEVICE=0x0f,
+ TEMPERATURE_DEVICE=0x10,
+ TEMPERATURE2_DEVICE=0x11,
+ TEMPERATURE5_DEVICE=0x15,
+ HUMIDITY1_DEVICE=0x20,
+ SWITCHX_DEVICE=0x28, // new switch 3,4,8
+ CONTACT00_DEVICE=0x30, CONTACT01_DEVICE=0x31, CONTACT02_DEVICE=0x32, CONTACT03_DEVICE=0x33,
+ CONTACT04_DEVICE=0x34, CONTACT05_DEVICE=0x35, CONTACT06_DEVICE=0x36, CONTACT07_DEVICE=0x37,
+ CONTACT08_DEVICE=0x38, CONTACT09_DEVICE=0x39, CONTACT10_DEVICE=0x3a, CONTACT11_DEVICE=0x3b,
+ CONTACT12_DEVICE=0x3c, CONTACT13_DEVICE=0x3d, CONTACT14_DEVICE=0x3e, CONTACT15_DEVICE=0x3f,
+ F4_DEVICE=0x40,
+ KEYC01_DEVICE=0x41, KEYC16_DEVICE=0x42,
+ ADC0800_DEVICE=0x50, ADC0801_DEVICE=0x51, ADC0802_DEVICE=0x52, ADC0803_DEVICE=0x53,
+ COUNTER00_DEVICE=0x60,
+ ENCODER01_DEVICE=0x80,
+ BUTTON_NODEVICE=0x1000
+ } ;
+ private:
+ class CUSBaccessBasic * X ; // avoid export of internal USB variables
+
+ public:
+ CUSBaccess() ;
+ virtual ~CUSBaccess() ; // maybe used as base class
+
+ virtual int OpenCleware() ; // returns number of found Cleware devices
+ virtual int CloseCleware() ; // close all Cleware devices
+ virtual int Recover(int devNum) ; // try to find disconnected devices, returns true if succeeded
+ virtual HANDLE GetHandle(int deviceNo) ;
+ virtual int GetValue(int deviceNo, unsigned char *buf, int bufsize) ;
+ virtual int SetValue(int deviceNo, unsigned char *buf, int bufsize) ;
+ virtual int SetLED(int deviceNo, enum LED_IDs Led, int value) ; // value: 0=off 7=medium 15=highlight
+ virtual int SetSwitch(int deviceNo, enum SWITCH_IDs Switch, int On) ; // On: 0=off, 1=on
+ virtual int GetSwitch(int deviceNo, enum SWITCH_IDs Switch) ; // On: 0=off, 1=on, -1=error
+ virtual int GetSeqSwitch(int deviceNo, enum SWITCH_IDs Switch, int seqNum) ; // On: 0=off, 1=on, -1=error
+ virtual int GetSwitchConfig(int deviceNo, int *switchCount, int *buttonAvailable) ;
+ virtual int GetTemperature(int deviceNo, double *Temperature, int *timeID) ;
+ virtual int GetHumidity(int deviceNo, double *Humidity, int *timeID) ;
+ virtual int ResetDevice(int deviceNo) ;
+ virtual int StartDevice(int deviceNo) ;
+ virtual int CalmWatchdog(int deviceNo, int minutes, int minutes2restart) ;
+ virtual int GetVersion(int deviceNo) ;
+ virtual int GetUSBType(int deviceNo) ;
+ virtual int GetSerialNumber(int deviceNo) ;
+ virtual int GetDLLVersion() { return USBaccessVersion ; }
+ virtual int GetManualOnCount(int deviceNo) ; // returns how often switch is manually turned on
+ virtual int GetManualOnTime(int deviceNo) ; // returns how long (seconds) switch is manually turned on
+ virtual int GetOnlineOnCount(int deviceNo) ; // returns how often switch is turned on by USB command
+ virtual int GetOnlineOnTime(int deviceNo) ; // returns how long (seconds) switch is turned on by USB command
+ virtual int GetMultiSwitch(int deviceNo, unsigned long int *mask, unsigned long int *value, int seqNumber) ;
+ virtual int SetMultiSwitch(int deviceNo, unsigned long int value) ;
+ virtual int SetMultiConfig(int deviceNo, unsigned long int directions) ;
+ virtual int GetCounter(int deviceNo, enum COUNTER_IDs counterID) ; // COUNTER_IDs ununsed until now
+ virtual int SetCounter(int deviceNo, int counter, enum COUNTER_IDs counterID) ; // -1=error, COUNTER_IDs ununsed until now
+ virtual int SyncDevice(int deviceNo, unsigned long int mask) ;
+ virtual int GetHWversion(int deviceNo) ; // return HWversion (0 for pre 2014 designed devices, 13 for new devices)
+ virtual int IOX(int deviceNo, int addr, int data) ; // for internal use only, wrong usage may destroy device
+ virtual void DebugWrite(char *s) ;
+ virtual void DebugWrite(char *f, int a1) ;
+ virtual void DebugWrite(char *f, int a1, int a2) ;
+ virtual void DebugWrite(char *f, int a1, int a2, int a3) ;
+ virtual void DebugWrite(char *f, int a1, int a2, int a3, int a4) ;
+ virtual void Sleep(int ms) { usleep(ms * 1000) ; } // for Linux
+ } ;
+%}
+
+const int USBaccessVersion = 433 ;
+
+class CUSBaccess {
+ public:
+ enum USBactions { LEDs=0, EEwrite=1, EEread=2, Reset=3, KeepCalm=4, GetInfo=5,
+ StartMeasuring=6, // USB-Humidity
+ Configure=7, // USB-IO16-V10, USB-Counter-V05
+ RunPoint=10, // USB-Encoder
+ ContactWrite=11, // 613er IO16
+ ContactRead=12 // 613er IO16
+ } ;
+ enum USBInfoType { OnlineTime=1, OnlineCount=2, ManualTime=3, ManualCount=4 } ;
+ enum LED_IDs { LED_0=0, LED_1=1, LED_2=2, LED_3=3 } ;
+ enum COUNTER_IDs { COUNTER_0=0, COUNTER_1=1 } ;
+ enum SWITCH_IDs { SWITCH_0=0x10, SWITCH_1=0x11, SWITCH_2=0x12, SWITCH_3=0x13,
+ SWITCH_4=0x14, SWITCH_5=0x15, SWITCH_6=0x16, SWITCH_7=0x17,
+ SWITCH_8=0x18, SWITCH_9=0x19, SWITCH_10=0x1a, SWITCH_11=0x1b,
+ SWITCH_12=0x1c, SWITCH_13=0x1d, SWITCH_14=0x1e, SWITCH_15=0x1f
+ } ;
+ enum USBtype_enum { ILLEGAL_DEVICE=0,
+ LED_DEVICE=0x01,
+ POWER_DEVICE=0x02,
+ WATCHDOG_DEVICE=0x05,
+ AUTORESET_DEVICE=0x06,
+ WATCHDOGXP_DEVICE=0x07,
+ SWITCH1_DEVICE=0x08,
+ SWITCH2_DEVICE=0x09, SWITCH3_DEVICE=0x0a, SWITCH4_DEVICE=0x0b,
+ SWITCH5_DEVICE=0x0c, SWITCH6_DEVICE=0x0d, SWITCH7_DEVICE=0x0e, SWITCH8_DEVICE=0x0f,
+ TEMPERATURE_DEVICE=0x10,
+ TEMPERATURE2_DEVICE=0x11,
+ TEMPERATURE5_DEVICE=0x15,
+ HUMIDITY1_DEVICE=0x20,
+ SWITCHX_DEVICE=0x28, // new switch 3,4,8
+ CONTACT00_DEVICE=0x30, CONTACT01_DEVICE=0x31, CONTACT02_DEVICE=0x32, CONTACT03_DEVICE=0x33,
+ CONTACT04_DEVICE=0x34, CONTACT05_DEVICE=0x35, CONTACT06_DEVICE=0x36, CONTACT07_DEVICE=0x37,
+ CONTACT08_DEVICE=0x38, CONTACT09_DEVICE=0x39, CONTACT10_DEVICE=0x3a, CONTACT11_DEVICE=0x3b,
+ CONTACT12_DEVICE=0x3c, CONTACT13_DEVICE=0x3d, CONTACT14_DEVICE=0x3e, CONTACT15_DEVICE=0x3f,
+ F4_DEVICE=0x40,
+ KEYC01_DEVICE=0x41, KEYC16_DEVICE=0x42,
+ ADC0800_DEVICE=0x50, ADC0801_DEVICE=0x51, ADC0802_DEVICE=0x52, ADC0803_DEVICE=0x53,
+ COUNTER00_DEVICE=0x60,
+ ENCODER01_DEVICE=0x80,
+ BUTTON_NODEVICE=0x1000
+ } ;
+ private:
+ class CUSBaccessBasic * X ; // avoid export of internal USB variables
+
+ public:
+ CUSBaccess() ;
+ virtual ~CUSBaccess() ; // maybe used as base class
+
+ virtual int OpenCleware() ; // returns number of found Cleware devices
+ virtual int CloseCleware() ; // close all Cleware devices
+ virtual int Recover(int devNum) ; // try to find disconnected devices, returns true if succeeded
+ virtual HANDLE GetHandle(int deviceNo) ;
+ virtual int GetValue(int deviceNo, unsigned char *buf, int bufsize) ;
+ virtual int SetValue(int deviceNo, unsigned char *buf, int bufsize) ;
+ virtual int SetLED(int deviceNo, enum LED_IDs Led, int value) ; // value: 0=off 7=medium 15=highlight
+ virtual int SetSwitch(int deviceNo, enum SWITCH_IDs Switch, int On) ; // On: 0=off, 1=on
+ virtual int GetSwitch(int deviceNo, enum SWITCH_IDs Switch) ; // On: 0=off, 1=on, -1=error
+ virtual int GetSeqSwitch(int deviceNo, enum SWITCH_IDs Switch, int seqNum) ; // On: 0=off, 1=on, -1=error
+ virtual int GetSwitchConfig(int deviceNo, int *switchCount, int *buttonAvailable) ;
+ virtual int GetTemperature(int deviceNo, double *Temperature, int *timeID) ;
+ virtual int GetHumidity(int deviceNo, double *Humidity, int *timeID) ;
+ virtual int ResetDevice(int deviceNo) ;
+ virtual int StartDevice(int deviceNo) ;
+ virtual int CalmWatchdog(int deviceNo, int minutes, int minutes2restart) ;
+ virtual int GetVersion(int deviceNo) ;
+ virtual int GetUSBType(int deviceNo) ;
+ virtual int GetSerialNumber(int deviceNo) ;
+ virtual int GetDLLVersion() { return USBaccessVersion ; }
+ virtual int GetManualOnCount(int deviceNo) ; // returns how often switch is manually turned on
+ virtual int GetManualOnTime(int deviceNo) ; // returns how long (seconds) switch is manually turned on
+ virtual int GetOnlineOnCount(int deviceNo) ; // returns how often switch is turned on by USB command
+ virtual int GetOnlineOnTime(int deviceNo) ; // returns how long (seconds) switch is turned on by USB command
+ virtual int GetMultiSwitch(int deviceNo, unsigned long int *mask, unsigned long int *value, int seqNumber) ;
+ virtual int SetMultiSwitch(int deviceNo, unsigned long int value) ;
+ virtual int SetMultiConfig(int deviceNo, unsigned long int directions) ;
+ virtual int GetCounter(int deviceNo, enum COUNTER_IDs counterID) ; // COUNTER_IDs ununsed until now
+ virtual int SetCounter(int deviceNo, int counter, enum COUNTER_IDs counterID) ; // -1=error, COUNTER_IDs ununsed until now
+ virtual int SyncDevice(int deviceNo, unsigned long int mask) ;
+ virtual int GetHWversion(int deviceNo) ; // return HWversion (0 for pre 2014 designed devices, 13 for new devices)
+ virtual int IOX(int deviceNo, int addr, int data) ; // for internal use only, wrong usage may destroy device
+ virtual void DebugWrite(char *s) ;
+ virtual void DebugWrite(char *f, int a1) ;
+ virtual void DebugWrite(char *f, int a1, int a2) ;
+ virtual void DebugWrite(char *f, int a1, int a2, int a3) ;
+ virtual void DebugWrite(char *f, int a1, int a2, int a3, int a4) ;
+ virtual void Sleep(int ms) { usleep(ms * 1000) ; } // for Linux
+ } ;
diff --git a/clewarecontrol.1 b/clewarecontrol.1
new file mode 100644
index 0000000..eb86c16
--- /dev/null
+++ b/clewarecontrol.1
@@ -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
index 0000000..d0eeaee
--- /dev/null
+++ b/debian/changelog
@@ -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
index 0000000..ec63514
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..c6033d3
--- /dev/null
+++ b/debian/control
@@ -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
index 0000000..8cf23f1
--- /dev/null
+++ b/debian/copyright
@@ -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
index 0000000..2fcf0ac
--- /dev/null
+++ b/debian/docs
@@ -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
index 0000000..4595ee6
--- /dev/null
+++ b/debian/files
@@ -0,0 +1 @@
+clewarecontrol_4.3-1_amd64.deb devel optional
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..79fd842
--- /dev/null
+++ b/debian/rules
@@ -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
index 0000000..163aaf8
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/error.cpp b/error.cpp
new file mode 100644
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
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
index 0000000..44e669f
--- /dev/null
+++ b/example.pl
@@ -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
index 0000000..7329f07
--- /dev/null
+++ b/example.py
@@ -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
index 0000000..13caae2
--- /dev/null
+++ b/examples/Munin/cleware-munin.sh
@@ -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
index 0000000..6f3ebee
--- /dev/null
+++ b/examples/Nagios/RCS/cleware_nagios_script,v
@@ -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
index 0000000..812cce7
--- /dev/null
+++ b/examples/Nagios/cleware_nagios_script
@@ -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
index 0000000..8f8dfe5
--- /dev/null
+++ b/examples/Nagios/nagios.txt
@@ -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
index 0000000..ad67ec7
--- /dev/null
+++ b/examples/Nagios/seealso.txt
@@ -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
index 0000000..c261043
--- /dev/null
+++ b/examples/RRD/add_measurement_to_rrd
@@ -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
index 0000000..64cba57
--- /dev/null
+++ b/examples/RRD/draw_graph_from_rrd
@@ -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
index 0000000..ef244c3
--- /dev/null
+++ b/examples/RRD/make_rrd
@@ -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
index 0000000..5e30e31
--- /dev/null
+++ b/examples/RRD/rrd.txt
@@ -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
index 0000000..c7bc3b4
--- /dev/null
+++ b/examples/Watchdog/clewarewatchdog
@@ -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
index 0000000..f33d560
--- /dev/null
+++ b/examples/Watchdog/watchdog.txt
@@ -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
index 0000000..ea89f33
--- /dev/null
+++ b/examples/ampel/ampel.txt
@@ -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
index 0000000..ffa12e6
--- /dev/null
+++ b/examples/ampel/script.sh
@@ -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
index 0000000..650ae9f
--- /dev/null
+++ b/install-lib.pl
@@ -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
index 0000000..37895c7
--- /dev/null
+++ b/install-lib.py
@@ -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
index 0000000..38bb635
--- /dev/null
+++ b/mac-hidapi/hid.c
@@ -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
index 0000000..e5bc2dc
--- /dev/null
+++ b/mac-hidapi/hidapi.h
@@ -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
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
index 0000000..89a5fd4
--- /dev/null
+++ b/readme-mac.txt
@@ -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
index 0000000..94c0265
--- /dev/null
+++ b/readme-perl.txt
@@ -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
index 0000000..62c9fed
--- /dev/null
+++ b/readme-python.txt
@@ -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
index 0000000..d2f0b78
--- /dev/null
+++ b/readme.txt
@@ -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
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
index 0000000..59168ea
--- /dev/null
+++ b/setup.py_CI
@@ -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"],
+ )