diff options
author | Donghoon Shin <dhs.shin@samsung.com> | 2016-09-19 17:36:01 +0900 |
---|---|---|
committer | Donghoon Shin <dhs.shin@samsung.com> | 2016-09-19 17:36:01 +0900 |
commit | e8acd13cc87ea038ecd6103e4088ce3cf5d501d7 (patch) | |
tree | 4c7c8cc683a297463996aa286f2f7758e8691b8f | |
parent | b95c2492274542bc4718a863f5d88f37a0a788ab (diff) | |
download | clewarecontrol-accepted/tizen_devbase_tools.tar.gz clewarecontrol-accepted/tizen_devbase_tools.tar.bz2 clewarecontrol-accepted/tizen_devbase_tools.zip |
Update initial source codesHEADupstream/4.3submit/trunk/20201029.132130submit/trunk/20201029.114030submit/trunk/20200409.202020submit/trunk/20200409.200220submit/trunk/20200409.194520submit/trunk/20191101.102136submit/trunk/20191030.112603submit/trunk/20191017.233826submit/trunk/20191017.111201submit/trunk/20190927.012842submit/devel/20190730.075528submit/devel/20190730.074447accepted/tools/devbase/tools/legacy/20240424.050722accepted/tools/devbase/tools/legacy/20240423.040742accepted/tools/devbase/tools/legacy/20240422.110908accepted/tizen/devbase/tools/20190927.045004release-20160930masterdevelaccepted/tools_devbase_tools_legacyaccepted/tizen_devbase_tools
Change-Id: I59bac2188ffbfe5a2ad2d9dcb33847aabfaffe44
47 files changed, 7681 insertions, 0 deletions
@@ -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); +} @@ -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"], + ) |