Added missing files from previous commits
authorSam Lantinga <slouken@libsdl.org>
Thu, 09 Aug 2018 16:05:48 -0700
changeset 120988eb14aba4e87
parent 12097 f44ed5271f78
child 12099 d18ba4892cff
Added missing files from previous commits
src/hidapi/AUTHORS.txt
src/hidapi/HACKING.txt
src/hidapi/LICENSE-bsd.txt
src/hidapi/LICENSE-gpl3.txt
src/hidapi/LICENSE-orig.txt
src/hidapi/LICENSE.txt
src/hidapi/Makefile.am
src/hidapi/README.txt
src/hidapi/android/hid.cpp
src/hidapi/android/jni/Android.mk
src/hidapi/android/jni/Application.mk
src/hidapi/android/project.properties
src/hidapi/bootstrap
src/hidapi/configure.ac
src/hidapi/doxygen/Doxyfile
src/hidapi/hidapi/hidapi.h
src/hidapi/hidtest/Makefile.am
src/hidapi/hidtest/hidtest.cpp
src/hidapi/ios/Makefile-manual
src/hidapi/ios/Makefile.am
src/hidapi/ios/hid.mm
src/hidapi/libusb/Makefile-manual
src/hidapi/libusb/Makefile.am
src/hidapi/libusb/Makefile.freebsd
src/hidapi/libusb/Makefile.linux
src/hidapi/libusb/hid.c
src/hidapi/libusb/hidusb.cpp
src/hidapi/linux/Makefile-manual
src/hidapi/linux/Makefile.am
src/hidapi/linux/README.txt
src/hidapi/linux/hid.c
src/hidapi/linux/hid.cpp
src/hidapi/linux/hidraw.cpp
src/hidapi/m4/ax_pthread.m4
src/hidapi/m4/pkg.m4
src/hidapi/mac/Makefile-manual
src/hidapi/mac/Makefile.am
src/hidapi/mac/hid.c
src/hidapi/pc/hidapi-hidraw.pc.in
src/hidapi/pc/hidapi-libusb.pc.in
src/hidapi/pc/hidapi.pc.in
src/hidapi/testgui/Makefile-manual
src/hidapi/testgui/Makefile.am
src/hidapi/testgui/Makefile.freebsd
src/hidapi/testgui/Makefile.linux
src/hidapi/testgui/Makefile.mac
src/hidapi/testgui/Makefile.mingw
src/hidapi/testgui/TestGUI.app.in/Contents/Info.plist
src/hidapi/testgui/TestGUI.app.in/Contents/PkgInfo
src/hidapi/testgui/TestGUI.app.in/Contents/Resources/English.lproj/InfoPlist.strings
src/hidapi/testgui/TestGUI.app.in/Contents/Resources/Signal11.icns
src/hidapi/testgui/copy_to_bundle.sh
src/hidapi/testgui/mac_support.cpp
src/hidapi/testgui/mac_support.h
src/hidapi/testgui/mac_support_cocoa.m
src/hidapi/testgui/start.sh
src/hidapi/testgui/test.cpp
src/hidapi/testgui/testgui.sln
src/hidapi/testgui/testgui.vcproj
src/hidapi/udev/99-hid.rules
src/hidapi/windows/Makefile-manual
src/hidapi/windows/Makefile.am
src/hidapi/windows/Makefile.mingw
src/hidapi/windows/ddk_build/hidapi.def
src/hidapi/windows/ddk_build/makefile
src/hidapi/windows/ddk_build/sources
src/hidapi/windows/hid.c
src/hidapi/windows/hidapi.sln
src/hidapi/windows/hidapi.vcproj
src/hidapi/windows/hidtest.vcproj
src/joystick/controller_type.h
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/hidapi/AUTHORS.txt	Thu Aug 09 16:05:48 2018 -0700
     1.3 @@ -0,0 +1,16 @@
     1.4 +
     1.5 +HIDAPI Authors:
     1.6 +
     1.7 +Alan Ott <alan@signal11.us>:
     1.8 +	Original Author and Maintainer
     1.9 +	Linux, Windows, and Mac implementations
    1.10 +
    1.11 +Ludovic Rousseau <rousseau@debian.org>:
    1.12 +	Formatting for Doxygen documentation
    1.13 +	Bug fixes
    1.14 +	Correctness fixes
    1.15 +
    1.16 +
    1.17 +For a comprehensive list of contributions, see the commit list at github:
    1.18 +	http://github.com/signal11/hidapi/commits/master
    1.19 +
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/hidapi/HACKING.txt	Thu Aug 09 16:05:48 2018 -0700
     2.3 @@ -0,0 +1,15 @@
     2.4 +This file is mostly for the maintainer.
     2.5 +
     2.6 +1. Build hidapi.dll
     2.7 +2. Build hidtest.exe in DEBUG and RELEASE
     2.8 +3. Commit all
     2.9 +
    2.10 +4. Run the Following
    2.11 +	export VERSION=0.1.0
    2.12 +	export TAG_NAME=hidapi-$VERSION
    2.13 +	git tag $TAG_NAME
    2.14 +	git archive --format zip --prefix $TAG_NAME/ $TAG_NAME >../$TAG_NAME.zip
    2.15 +5. Test the zip file.
    2.16 +6. Run the following:
    2.17 +	git push origin $TAG_NAME
    2.18 +
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/hidapi/LICENSE-bsd.txt	Thu Aug 09 16:05:48 2018 -0700
     3.3 @@ -0,0 +1,26 @@
     3.4 +Copyright (c) 2010, Alan Ott, Signal 11 Software
     3.5 +All rights reserved.
     3.6 +
     3.7 +Redistribution and use in source and binary forms, with or without
     3.8 +modification, are permitted provided that the following conditions are met:
     3.9 +
    3.10 +    * Redistributions of source code must retain the above copyright notice,
    3.11 +      this list of conditions and the following disclaimer.
    3.12 +    * Redistributions in binary form must reproduce the above copyright
    3.13 +      notice, this list of conditions and the following disclaimer in the
    3.14 +      documentation and/or other materials provided with the distribution.
    3.15 +    * Neither the name of Signal 11 Software nor the names of its
    3.16 +      contributors may be used to endorse or promote products derived from
    3.17 +      this software without specific prior written permission.
    3.18 +
    3.19 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    3.20 +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    3.21 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    3.22 +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    3.23 +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    3.24 +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    3.25 +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    3.26 +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    3.27 +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    3.28 +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    3.29 +POSSIBILITY OF SUCH DAMAGE.
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/hidapi/LICENSE-gpl3.txt	Thu Aug 09 16:05:48 2018 -0700
     4.3 @@ -0,0 +1,674 @@
     4.4 +                    GNU GENERAL PUBLIC LICENSE
     4.5 +                       Version 3, 29 June 2007
     4.6 +
     4.7 + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
     4.8 + Everyone is permitted to copy and distribute verbatim copies
     4.9 + of this license document, but changing it is not allowed.
    4.10 +
    4.11 +                            Preamble
    4.12 +
    4.13 +  The GNU General Public License is a free, copyleft license for
    4.14 +software and other kinds of works.
    4.15 +
    4.16 +  The licenses for most software and other practical works are designed
    4.17 +to take away your freedom to share and change the works.  By contrast,
    4.18 +the GNU General Public License is intended to guarantee your freedom to
    4.19 +share and change all versions of a program--to make sure it remains free
    4.20 +software for all its users.  We, the Free Software Foundation, use the
    4.21 +GNU General Public License for most of our software; it applies also to
    4.22 +any other work released this way by its authors.  You can apply it to
    4.23 +your programs, too.
    4.24 +
    4.25 +  When we speak of free software, we are referring to freedom, not
    4.26 +price.  Our General Public Licenses are designed to make sure that you
    4.27 +have the freedom to distribute copies of free software (and charge for
    4.28 +them if you wish), that you receive source code or can get it if you
    4.29 +want it, that you can change the software or use pieces of it in new
    4.30 +free programs, and that you know you can do these things.
    4.31 +
    4.32 +  To protect your rights, we need to prevent others from denying you
    4.33 +these rights or asking you to surrender the rights.  Therefore, you have
    4.34 +certain responsibilities if you distribute copies of the software, or if
    4.35 +you modify it: responsibilities to respect the freedom of others.
    4.36 +
    4.37 +  For example, if you distribute copies of such a program, whether
    4.38 +gratis or for a fee, you must pass on to the recipients the same
    4.39 +freedoms that you received.  You must make sure that they, too, receive
    4.40 +or can get the source code.  And you must show them these terms so they
    4.41 +know their rights.
    4.42 +
    4.43 +  Developers that use the GNU GPL protect your rights with two steps:
    4.44 +(1) assert copyright on the software, and (2) offer you this License
    4.45 +giving you legal permission to copy, distribute and/or modify it.
    4.46 +
    4.47 +  For the developers' and authors' protection, the GPL clearly explains
    4.48 +that there is no warranty for this free software.  For both users' and
    4.49 +authors' sake, the GPL requires that modified versions be marked as
    4.50 +changed, so that their problems will not be attributed erroneously to
    4.51 +authors of previous versions.
    4.52 +
    4.53 +  Some devices are designed to deny users access to install or run
    4.54 +modified versions of the software inside them, although the manufacturer
    4.55 +can do so.  This is fundamentally incompatible with the aim of
    4.56 +protecting users' freedom to change the software.  The systematic
    4.57 +pattern of such abuse occurs in the area of products for individuals to
    4.58 +use, which is precisely where it is most unacceptable.  Therefore, we
    4.59 +have designed this version of the GPL to prohibit the practice for those
    4.60 +products.  If such problems arise substantially in other domains, we
    4.61 +stand ready to extend this provision to those domains in future versions
    4.62 +of the GPL, as needed to protect the freedom of users.
    4.63 +
    4.64 +  Finally, every program is threatened constantly by software patents.
    4.65 +States should not allow patents to restrict development and use of
    4.66 +software on general-purpose computers, but in those that do, we wish to
    4.67 +avoid the special danger that patents applied to a free program could
    4.68 +make it effectively proprietary.  To prevent this, the GPL assures that
    4.69 +patents cannot be used to render the program non-free.
    4.70 +
    4.71 +  The precise terms and conditions for copying, distribution and
    4.72 +modification follow.
    4.73 +
    4.74 +                       TERMS AND CONDITIONS
    4.75 +
    4.76 +  0. Definitions.
    4.77 +
    4.78 +  "This License" refers to version 3 of the GNU General Public License.
    4.79 +
    4.80 +  "Copyright" also means copyright-like laws that apply to other kinds of
    4.81 +works, such as semiconductor masks.
    4.82 +
    4.83 +  "The Program" refers to any copyrightable work licensed under this
    4.84 +License.  Each licensee is addressed as "you".  "Licensees" and
    4.85 +"recipients" may be individuals or organizations.
    4.86 +
    4.87 +  To "modify" a work means to copy from or adapt all or part of the work
    4.88 +in a fashion requiring copyright permission, other than the making of an
    4.89 +exact copy.  The resulting work is called a "modified version" of the
    4.90 +earlier work or a work "based on" the earlier work.
    4.91 +
    4.92 +  A "covered work" means either the unmodified Program or a work based
    4.93 +on the Program.
    4.94 +
    4.95 +  To "propagate" a work means to do anything with it that, without
    4.96 +permission, would make you directly or secondarily liable for
    4.97 +infringement under applicable copyright law, except executing it on a
    4.98 +computer or modifying a private copy.  Propagation includes copying,
    4.99 +distribution (with or without modification), making available to the
   4.100 +public, and in some countries other activities as well.
   4.101 +
   4.102 +  To "convey" a work means any kind of propagation that enables other
   4.103 +parties to make or receive copies.  Mere interaction with a user through
   4.104 +a computer network, with no transfer of a copy, is not conveying.
   4.105 +
   4.106 +  An interactive user interface displays "Appropriate Legal Notices"
   4.107 +to the extent that it includes a convenient and prominently visible
   4.108 +feature that (1) displays an appropriate copyright notice, and (2)
   4.109 +tells the user that there is no warranty for the work (except to the
   4.110 +extent that warranties are provided), that licensees may convey the
   4.111 +work under this License, and how to view a copy of this License.  If
   4.112 +the interface presents a list of user commands or options, such as a
   4.113 +menu, a prominent item in the list meets this criterion.
   4.114 +
   4.115 +  1. Source Code.
   4.116 +
   4.117 +  The "source code" for a work means the preferred form of the work
   4.118 +for making modifications to it.  "Object code" means any non-source
   4.119 +form of a work.
   4.120 +
   4.121 +  A "Standard Interface" means an interface that either is an official
   4.122 +standard defined by a recognized standards body, or, in the case of
   4.123 +interfaces specified for a particular programming language, one that
   4.124 +is widely used among developers working in that language.
   4.125 +
   4.126 +  The "System Libraries" of an executable work include anything, other
   4.127 +than the work as a whole, that (a) is included in the normal form of
   4.128 +packaging a Major Component, but which is not part of that Major
   4.129 +Component, and (b) serves only to enable use of the work with that
   4.130 +Major Component, or to implement a Standard Interface for which an
   4.131 +implementation is available to the public in source code form.  A
   4.132 +"Major Component", in this context, means a major essential component
   4.133 +(kernel, window system, and so on) of the specific operating system
   4.134 +(if any) on which the executable work runs, or a compiler used to
   4.135 +produce the work, or an object code interpreter used to run it.
   4.136 +
   4.137 +  The "Corresponding Source" for a work in object code form means all
   4.138 +the source code needed to generate, install, and (for an executable
   4.139 +work) run the object code and to modify the work, including scripts to
   4.140 +control those activities.  However, it does not include the work's
   4.141 +System Libraries, or general-purpose tools or generally available free
   4.142 +programs which are used unmodified in performing those activities but
   4.143 +which are not part of the work.  For example, Corresponding Source
   4.144 +includes interface definition files associated with source files for
   4.145 +the work, and the source code for shared libraries and dynamically
   4.146 +linked subprograms that the work is specifically designed to require,
   4.147 +such as by intimate data communication or control flow between those
   4.148 +subprograms and other parts of the work.
   4.149 +
   4.150 +  The Corresponding Source need not include anything that users
   4.151 +can regenerate automatically from other parts of the Corresponding
   4.152 +Source.
   4.153 +
   4.154 +  The Corresponding Source for a work in source code form is that
   4.155 +same work.
   4.156 +
   4.157 +  2. Basic Permissions.
   4.158 +
   4.159 +  All rights granted under this License are granted for the term of
   4.160 +copyright on the Program, and are irrevocable provided the stated
   4.161 +conditions are met.  This License explicitly affirms your unlimited
   4.162 +permission to run the unmodified Program.  The output from running a
   4.163 +covered work is covered by this License only if the output, given its
   4.164 +content, constitutes a covered work.  This License acknowledges your
   4.165 +rights of fair use or other equivalent, as provided by copyright law.
   4.166 +
   4.167 +  You may make, run and propagate covered works that you do not
   4.168 +convey, without conditions so long as your license otherwise remains
   4.169 +in force.  You may convey covered works to others for the sole purpose
   4.170 +of having them make modifications exclusively for you, or provide you
   4.171 +with facilities for running those works, provided that you comply with
   4.172 +the terms of this License in conveying all material for which you do
   4.173 +not control copyright.  Those thus making or running the covered works
   4.174 +for you must do so exclusively on your behalf, under your direction
   4.175 +and control, on terms that prohibit them from making any copies of
   4.176 +your copyrighted material outside their relationship with you.
   4.177 +
   4.178 +  Conveying under any other circumstances is permitted solely under
   4.179 +the conditions stated below.  Sublicensing is not allowed; section 10
   4.180 +makes it unnecessary.
   4.181 +
   4.182 +  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
   4.183 +
   4.184 +  No covered work shall be deemed part of an effective technological
   4.185 +measure under any applicable law fulfilling obligations under article
   4.186 +11 of the WIPO copyright treaty adopted on 20 December 1996, or
   4.187 +similar laws prohibiting or restricting circumvention of such
   4.188 +measures.
   4.189 +
   4.190 +  When you convey a covered work, you waive any legal power to forbid
   4.191 +circumvention of technological measures to the extent such circumvention
   4.192 +is effected by exercising rights under this License with respect to
   4.193 +the covered work, and you disclaim any intention to limit operation or
   4.194 +modification of the work as a means of enforcing, against the work's
   4.195 +users, your or third parties' legal rights to forbid circumvention of
   4.196 +technological measures.
   4.197 +
   4.198 +  4. Conveying Verbatim Copies.
   4.199 +
   4.200 +  You may convey verbatim copies of the Program's source code as you
   4.201 +receive it, in any medium, provided that you conspicuously and
   4.202 +appropriately publish on each copy an appropriate copyright notice;
   4.203 +keep intact all notices stating that this License and any
   4.204 +non-permissive terms added in accord with section 7 apply to the code;
   4.205 +keep intact all notices of the absence of any warranty; and give all
   4.206 +recipients a copy of this License along with the Program.
   4.207 +
   4.208 +  You may charge any price or no price for each copy that you convey,
   4.209 +and you may offer support or warranty protection for a fee.
   4.210 +
   4.211 +  5. Conveying Modified Source Versions.
   4.212 +
   4.213 +  You may convey a work based on the Program, or the modifications to
   4.214 +produce it from the Program, in the form of source code under the
   4.215 +terms of section 4, provided that you also meet all of these conditions:
   4.216 +
   4.217 +    a) The work must carry prominent notices stating that you modified
   4.218 +    it, and giving a relevant date.
   4.219 +
   4.220 +    b) The work must carry prominent notices stating that it is
   4.221 +    released under this License and any conditions added under section
   4.222 +    7.  This requirement modifies the requirement in section 4 to
   4.223 +    "keep intact all notices".
   4.224 +
   4.225 +    c) You must license the entire work, as a whole, under this
   4.226 +    License to anyone who comes into possession of a copy.  This
   4.227 +    License will therefore apply, along with any applicable section 7
   4.228 +    additional terms, to the whole of the work, and all its parts,
   4.229 +    regardless of how they are packaged.  This License gives no
   4.230 +    permission to license the work in any other way, but it does not
   4.231 +    invalidate such permission if you have separately received it.
   4.232 +
   4.233 +    d) If the work has interactive user interfaces, each must display
   4.234 +    Appropriate Legal Notices; however, if the Program has interactive
   4.235 +    interfaces that do not display Appropriate Legal Notices, your
   4.236 +    work need not make them do so.
   4.237 +
   4.238 +  A compilation of a covered work with other separate and independent
   4.239 +works, which are not by their nature extensions of the covered work,
   4.240 +and which are not combined with it such as to form a larger program,
   4.241 +in or on a volume of a storage or distribution medium, is called an
   4.242 +"aggregate" if the compilation and its resulting copyright are not
   4.243 +used to limit the access or legal rights of the compilation's users
   4.244 +beyond what the individual works permit.  Inclusion of a covered work
   4.245 +in an aggregate does not cause this License to apply to the other
   4.246 +parts of the aggregate.
   4.247 +
   4.248 +  6. Conveying Non-Source Forms.
   4.249 +
   4.250 +  You may convey a covered work in object code form under the terms
   4.251 +of sections 4 and 5, provided that you also convey the
   4.252 +machine-readable Corresponding Source under the terms of this License,
   4.253 +in one of these ways:
   4.254 +
   4.255 +    a) Convey the object code in, or embodied in, a physical product
   4.256 +    (including a physical distribution medium), accompanied by the
   4.257 +    Corresponding Source fixed on a durable physical medium
   4.258 +    customarily used for software interchange.
   4.259 +
   4.260 +    b) Convey the object code in, or embodied in, a physical product
   4.261 +    (including a physical distribution medium), accompanied by a
   4.262 +    written offer, valid for at least three years and valid for as
   4.263 +    long as you offer spare parts or customer support for that product
   4.264 +    model, to give anyone who possesses the object code either (1) a
   4.265 +    copy of the Corresponding Source for all the software in the
   4.266 +    product that is covered by this License, on a durable physical
   4.267 +    medium customarily used for software interchange, for a price no
   4.268 +    more than your reasonable cost of physically performing this
   4.269 +    conveying of source, or (2) access to copy the
   4.270 +    Corresponding Source from a network server at no charge.
   4.271 +
   4.272 +    c) Convey individual copies of the object code with a copy of the
   4.273 +    written offer to provide the Corresponding Source.  This
   4.274 +    alternative is allowed only occasionally and noncommercially, and
   4.275 +    only if you received the object code with such an offer, in accord
   4.276 +    with subsection 6b.
   4.277 +
   4.278 +    d) Convey the object code by offering access from a designated
   4.279 +    place (gratis or for a charge), and offer equivalent access to the
   4.280 +    Corresponding Source in the same way through the same place at no
   4.281 +    further charge.  You need not require recipients to copy the
   4.282 +    Corresponding Source along with the object code.  If the place to
   4.283 +    copy the object code is a network server, the Corresponding Source
   4.284 +    may be on a different server (operated by you or a third party)
   4.285 +    that supports equivalent copying facilities, provided you maintain
   4.286 +    clear directions next to the object code saying where to find the
   4.287 +    Corresponding Source.  Regardless of what server hosts the
   4.288 +    Corresponding Source, you remain obligated to ensure that it is
   4.289 +    available for as long as needed to satisfy these requirements.
   4.290 +
   4.291 +    e) Convey the object code using peer-to-peer transmission, provided
   4.292 +    you inform other peers where the object code and Corresponding
   4.293 +    Source of the work are being offered to the general public at no
   4.294 +    charge under subsection 6d.
   4.295 +
   4.296 +  A separable portion of the object code, whose source code is excluded
   4.297 +from the Corresponding Source as a System Library, need not be
   4.298 +included in conveying the object code work.
   4.299 +
   4.300 +  A "User Product" is either (1) a "consumer product", which means any
   4.301 +tangible personal property which is normally used for personal, family,
   4.302 +or household purposes, or (2) anything designed or sold for incorporation
   4.303 +into a dwelling.  In determining whether a product is a consumer product,
   4.304 +doubtful cases shall be resolved in favor of coverage.  For a particular
   4.305 +product received by a particular user, "normally used" refers to a
   4.306 +typical or common use of that class of product, regardless of the status
   4.307 +of the particular user or of the way in which the particular user
   4.308 +actually uses, or expects or is expected to use, the product.  A product
   4.309 +is a consumer product regardless of whether the product has substantial
   4.310 +commercial, industrial or non-consumer uses, unless such uses represent
   4.311 +the only significant mode of use of the product.
   4.312 +
   4.313 +  "Installation Information" for a User Product means any methods,
   4.314 +procedures, authorization keys, or other information required to install
   4.315 +and execute modified versions of a covered work in that User Product from
   4.316 +a modified version of its Corresponding Source.  The information must
   4.317 +suffice to ensure that the continued functioning of the modified object
   4.318 +code is in no case prevented or interfered with solely because
   4.319 +modification has been made.
   4.320 +
   4.321 +  If you convey an object code work under this section in, or with, or
   4.322 +specifically for use in, a User Product, and the conveying occurs as
   4.323 +part of a transaction in which the right of possession and use of the
   4.324 +User Product is transferred to the recipient in perpetuity or for a
   4.325 +fixed term (regardless of how the transaction is characterized), the
   4.326 +Corresponding Source conveyed under this section must be accompanied
   4.327 +by the Installation Information.  But this requirement does not apply
   4.328 +if neither you nor any third party retains the ability to install
   4.329 +modified object code on the User Product (for example, the work has
   4.330 +been installed in ROM).
   4.331 +
   4.332 +  The requirement to provide Installation Information does not include a
   4.333 +requirement to continue to provide support service, warranty, or updates
   4.334 +for a work that has been modified or installed by the recipient, or for
   4.335 +the User Product in which it has been modified or installed.  Access to a
   4.336 +network may be denied when the modification itself materially and
   4.337 +adversely affects the operation of the network or violates the rules and
   4.338 +protocols for communication across the network.
   4.339 +
   4.340 +  Corresponding Source conveyed, and Installation Information provided,
   4.341 +in accord with this section must be in a format that is publicly
   4.342 +documented (and with an implementation available to the public in
   4.343 +source code form), and must require no special password or key for
   4.344 +unpacking, reading or copying.
   4.345 +
   4.346 +  7. Additional Terms.
   4.347 +
   4.348 +  "Additional permissions" are terms that supplement the terms of this
   4.349 +License by making exceptions from one or more of its conditions.
   4.350 +Additional permissions that are applicable to the entire Program shall
   4.351 +be treated as though they were included in this License, to the extent
   4.352 +that they are valid under applicable law.  If additional permissions
   4.353 +apply only to part of the Program, that part may be used separately
   4.354 +under those permissions, but the entire Program remains governed by
   4.355 +this License without regard to the additional permissions.
   4.356 +
   4.357 +  When you convey a copy of a covered work, you may at your option
   4.358 +remove any additional permissions from that copy, or from any part of
   4.359 +it.  (Additional permissions may be written to require their own
   4.360 +removal in certain cases when you modify the work.)  You may place
   4.361 +additional permissions on material, added by you to a covered work,
   4.362 +for which you have or can give appropriate copyright permission.
   4.363 +
   4.364 +  Notwithstanding any other provision of this License, for material you
   4.365 +add to a covered work, you may (if authorized by the copyright holders of
   4.366 +that material) supplement the terms of this License with terms:
   4.367 +
   4.368 +    a) Disclaiming warranty or limiting liability differently from the
   4.369 +    terms of sections 15 and 16 of this License; or
   4.370 +
   4.371 +    b) Requiring preservation of specified reasonable legal notices or
   4.372 +    author attributions in that material or in the Appropriate Legal
   4.373 +    Notices displayed by works containing it; or
   4.374 +
   4.375 +    c) Prohibiting misrepresentation of the origin of that material, or
   4.376 +    requiring that modified versions of such material be marked in
   4.377 +    reasonable ways as different from the original version; or
   4.378 +
   4.379 +    d) Limiting the use for publicity purposes of names of licensors or
   4.380 +    authors of the material; or
   4.381 +
   4.382 +    e) Declining to grant rights under trademark law for use of some
   4.383 +    trade names, trademarks, or service marks; or
   4.384 +
   4.385 +    f) Requiring indemnification of licensors and authors of that
   4.386 +    material by anyone who conveys the material (or modified versions of
   4.387 +    it) with contractual assumptions of liability to the recipient, for
   4.388 +    any liability that these contractual assumptions directly impose on
   4.389 +    those licensors and authors.
   4.390 +
   4.391 +  All other non-permissive additional terms are considered "further
   4.392 +restrictions" within the meaning of section 10.  If the Program as you
   4.393 +received it, or any part of it, contains a notice stating that it is
   4.394 +governed by this License along with a term that is a further
   4.395 +restriction, you may remove that term.  If a license document contains
   4.396 +a further restriction but permits relicensing or conveying under this
   4.397 +License, you may add to a covered work material governed by the terms
   4.398 +of that license document, provided that the further restriction does
   4.399 +not survive such relicensing or conveying.
   4.400 +
   4.401 +  If you add terms to a covered work in accord with this section, you
   4.402 +must place, in the relevant source files, a statement of the
   4.403 +additional terms that apply to those files, or a notice indicating
   4.404 +where to find the applicable terms.
   4.405 +
   4.406 +  Additional terms, permissive or non-permissive, may be stated in the
   4.407 +form of a separately written license, or stated as exceptions;
   4.408 +the above requirements apply either way.
   4.409 +
   4.410 +  8. Termination.
   4.411 +
   4.412 +  You may not propagate or modify a covered work except as expressly
   4.413 +provided under this License.  Any attempt otherwise to propagate or
   4.414 +modify it is void, and will automatically terminate your rights under
   4.415 +this License (including any patent licenses granted under the third
   4.416 +paragraph of section 11).
   4.417 +
   4.418 +  However, if you cease all violation of this License, then your
   4.419 +license from a particular copyright holder is reinstated (a)
   4.420 +provisionally, unless and until the copyright holder explicitly and
   4.421 +finally terminates your license, and (b) permanently, if the copyright
   4.422 +holder fails to notify you of the violation by some reasonable means
   4.423 +prior to 60 days after the cessation.
   4.424 +
   4.425 +  Moreover, your license from a particular copyright holder is
   4.426 +reinstated permanently if the copyright holder notifies you of the
   4.427 +violation by some reasonable means, this is the first time you have
   4.428 +received notice of violation of this License (for any work) from that
   4.429 +copyright holder, and you cure the violation prior to 30 days after
   4.430 +your receipt of the notice.
   4.431 +
   4.432 +  Termination of your rights under this section does not terminate the
   4.433 +licenses of parties who have received copies or rights from you under
   4.434 +this License.  If your rights have been terminated and not permanently
   4.435 +reinstated, you do not qualify to receive new licenses for the same
   4.436 +material under section 10.
   4.437 +
   4.438 +  9. Acceptance Not Required for Having Copies.
   4.439 +
   4.440 +  You are not required to accept this License in order to receive or
   4.441 +run a copy of the Program.  Ancillary propagation of a covered work
   4.442 +occurring solely as a consequence of using peer-to-peer transmission
   4.443 +to receive a copy likewise does not require acceptance.  However,
   4.444 +nothing other than this License grants you permission to propagate or
   4.445 +modify any covered work.  These actions infringe copyright if you do
   4.446 +not accept this License.  Therefore, by modifying or propagating a
   4.447 +covered work, you indicate your acceptance of this License to do so.
   4.448 +
   4.449 +  10. Automatic Licensing of Downstream Recipients.
   4.450 +
   4.451 +  Each time you convey a covered work, the recipient automatically
   4.452 +receives a license from the original licensors, to run, modify and
   4.453 +propagate that work, subject to this License.  You are not responsible
   4.454 +for enforcing compliance by third parties with this License.
   4.455 +
   4.456 +  An "entity transaction" is a transaction transferring control of an
   4.457 +organization, or substantially all assets of one, or subdividing an
   4.458 +organization, or merging organizations.  If propagation of a covered
   4.459 +work results from an entity transaction, each party to that
   4.460 +transaction who receives a copy of the work also receives whatever
   4.461 +licenses to the work the party's predecessor in interest had or could
   4.462 +give under the previous paragraph, plus a right to possession of the
   4.463 +Corresponding Source of the work from the predecessor in interest, if
   4.464 +the predecessor has it or can get it with reasonable efforts.
   4.465 +
   4.466 +  You may not impose any further restrictions on the exercise of the
   4.467 +rights granted or affirmed under this License.  For example, you may
   4.468 +not impose a license fee, royalty, or other charge for exercise of
   4.469 +rights granted under this License, and you may not initiate litigation
   4.470 +(including a cross-claim or counterclaim in a lawsuit) alleging that
   4.471 +any patent claim is infringed by making, using, selling, offering for
   4.472 +sale, or importing the Program or any portion of it.
   4.473 +
   4.474 +  11. Patents.
   4.475 +
   4.476 +  A "contributor" is a copyright holder who authorizes use under this
   4.477 +License of the Program or a work on which the Program is based.  The
   4.478 +work thus licensed is called the contributor's "contributor version".
   4.479 +
   4.480 +  A contributor's "essential patent claims" are all patent claims
   4.481 +owned or controlled by the contributor, whether already acquired or
   4.482 +hereafter acquired, that would be infringed by some manner, permitted
   4.483 +by this License, of making, using, or selling its contributor version,
   4.484 +but do not include claims that would be infringed only as a
   4.485 +consequence of further modification of the contributor version.  For
   4.486 +purposes of this definition, "control" includes the right to grant
   4.487 +patent sublicenses in a manner consistent with the requirements of
   4.488 +this License.
   4.489 +
   4.490 +  Each contributor grants you a non-exclusive, worldwide, royalty-free
   4.491 +patent license under the contributor's essential patent claims, to
   4.492 +make, use, sell, offer for sale, import and otherwise run, modify and
   4.493 +propagate the contents of its contributor version.
   4.494 +
   4.495 +  In the following three paragraphs, a "patent license" is any express
   4.496 +agreement or commitment, however denominated, not to enforce a patent
   4.497 +(such as an express permission to practice a patent or covenant not to
   4.498 +sue for patent infringement).  To "grant" such a patent license to a
   4.499 +party means to make such an agreement or commitment not to enforce a
   4.500 +patent against the party.
   4.501 +
   4.502 +  If you convey a covered work, knowingly relying on a patent license,
   4.503 +and the Corresponding Source of the work is not available for anyone
   4.504 +to copy, free of charge and under the terms of this License, through a
   4.505 +publicly available network server or other readily accessible means,
   4.506 +then you must either (1) cause the Corresponding Source to be so
   4.507 +available, or (2) arrange to deprive yourself of the benefit of the
   4.508 +patent license for this particular work, or (3) arrange, in a manner
   4.509 +consistent with the requirements of this License, to extend the patent
   4.510 +license to downstream recipients.  "Knowingly relying" means you have
   4.511 +actual knowledge that, but for the patent license, your conveying the
   4.512 +covered work in a country, or your recipient's use of the covered work
   4.513 +in a country, would infringe one or more identifiable patents in that
   4.514 +country that you have reason to believe are valid.
   4.515 +
   4.516 +  If, pursuant to or in connection with a single transaction or
   4.517 +arrangement, you convey, or propagate by procuring conveyance of, a
   4.518 +covered work, and grant a patent license to some of the parties
   4.519 +receiving the covered work authorizing them to use, propagate, modify
   4.520 +or convey a specific copy of the covered work, then the patent license
   4.521 +you grant is automatically extended to all recipients of the covered
   4.522 +work and works based on it.
   4.523 +
   4.524 +  A patent license is "discriminatory" if it does not include within
   4.525 +the scope of its coverage, prohibits the exercise of, or is
   4.526 +conditioned on the non-exercise of one or more of the rights that are
   4.527 +specifically granted under this License.  You may not convey a covered
   4.528 +work if you are a party to an arrangement with a third party that is
   4.529 +in the business of distributing software, under which you make payment
   4.530 +to the third party based on the extent of your activity of conveying
   4.531 +the work, and under which the third party grants, to any of the
   4.532 +parties who would receive the covered work from you, a discriminatory
   4.533 +patent license (a) in connection with copies of the covered work
   4.534 +conveyed by you (or copies made from those copies), or (b) primarily
   4.535 +for and in connection with specific products or compilations that
   4.536 +contain the covered work, unless you entered into that arrangement,
   4.537 +or that patent license was granted, prior to 28 March 2007.
   4.538 +
   4.539 +  Nothing in this License shall be construed as excluding or limiting
   4.540 +any implied license or other defenses to infringement that may
   4.541 +otherwise be available to you under applicable patent law.
   4.542 +
   4.543 +  12. No Surrender of Others' Freedom.
   4.544 +
   4.545 +  If conditions are imposed on you (whether by court order, agreement or
   4.546 +otherwise) that contradict the conditions of this License, they do not
   4.547 +excuse you from the conditions of this License.  If you cannot convey a
   4.548 +covered work so as to satisfy simultaneously your obligations under this
   4.549 +License and any other pertinent obligations, then as a consequence you may
   4.550 +not convey it at all.  For example, if you agree to terms that obligate you
   4.551 +to collect a royalty for further conveying from those to whom you convey
   4.552 +the Program, the only way you could satisfy both those terms and this
   4.553 +License would be to refrain entirely from conveying the Program.
   4.554 +
   4.555 +  13. Use with the GNU Affero General Public License.
   4.556 +
   4.557 +  Notwithstanding any other provision of this License, you have
   4.558 +permission to link or combine any covered work with a work licensed
   4.559 +under version 3 of the GNU Affero General Public License into a single
   4.560 +combined work, and to convey the resulting work.  The terms of this
   4.561 +License will continue to apply to the part which is the covered work,
   4.562 +but the special requirements of the GNU Affero General Public License,
   4.563 +section 13, concerning interaction through a network will apply to the
   4.564 +combination as such.
   4.565 +
   4.566 +  14. Revised Versions of this License.
   4.567 +
   4.568 +  The Free Software Foundation may publish revised and/or new versions of
   4.569 +the GNU General Public License from time to time.  Such new versions will
   4.570 +be similar in spirit to the present version, but may differ in detail to
   4.571 +address new problems or concerns.
   4.572 +
   4.573 +  Each version is given a distinguishing version number.  If the
   4.574 +Program specifies that a certain numbered version of the GNU General
   4.575 +Public License "or any later version" applies to it, you have the
   4.576 +option of following the terms and conditions either of that numbered
   4.577 +version or of any later version published by the Free Software
   4.578 +Foundation.  If the Program does not specify a version number of the
   4.579 +GNU General Public License, you may choose any version ever published
   4.580 +by the Free Software Foundation.
   4.581 +
   4.582 +  If the Program specifies that a proxy can decide which future
   4.583 +versions of the GNU General Public License can be used, that proxy's
   4.584 +public statement of acceptance of a version permanently authorizes you
   4.585 +to choose that version for the Program.
   4.586 +
   4.587 +  Later license versions may give you additional or different
   4.588 +permissions.  However, no additional obligations are imposed on any
   4.589 +author or copyright holder as a result of your choosing to follow a
   4.590 +later version.
   4.591 +
   4.592 +  15. Disclaimer of Warranty.
   4.593 +
   4.594 +  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
   4.595 +APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
   4.596 +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
   4.597 +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
   4.598 +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   4.599 +PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
   4.600 +IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
   4.601 +ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
   4.602 +
   4.603 +  16. Limitation of Liability.
   4.604 +
   4.605 +  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
   4.606 +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
   4.607 +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
   4.608 +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
   4.609 +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
   4.610 +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
   4.611 +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
   4.612 +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
   4.613 +SUCH DAMAGES.
   4.614 +
   4.615 +  17. Interpretation of Sections 15 and 16.
   4.616 +
   4.617 +  If the disclaimer of warranty and limitation of liability provided
   4.618 +above cannot be given local legal effect according to their terms,
   4.619 +reviewing courts shall apply local law that most closely approximates
   4.620 +an absolute waiver of all civil liability in connection with the
   4.621 +Program, unless a warranty or assumption of liability accompanies a
   4.622 +copy of the Program in return for a fee.
   4.623 +
   4.624 +                     END OF TERMS AND CONDITIONS
   4.625 +
   4.626 +            How to Apply These Terms to Your New Programs
   4.627 +
   4.628 +  If you develop a new program, and you want it to be of the greatest
   4.629 +possible use to the public, the best way to achieve this is to make it
   4.630 +free software which everyone can redistribute and change under these terms.
   4.631 +
   4.632 +  To do so, attach the following notices to the program.  It is safest
   4.633 +to attach them to the start of each source file to most effectively
   4.634 +state the exclusion of warranty; and each file should have at least
   4.635 +the "copyright" line and a pointer to where the full notice is found.
   4.636 +
   4.637 +    <one line to give the program's name and a brief idea of what it does.>
   4.638 +    Copyright (C) <year>  <name of author>
   4.639 +
   4.640 +    This program is free software: you can redistribute it and/or modify
   4.641 +    it under the terms of the GNU General Public License as published by
   4.642 +    the Free Software Foundation, either version 3 of the License, or
   4.643 +    (at your option) any later version.
   4.644 +
   4.645 +    This program is distributed in the hope that it will be useful,
   4.646 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   4.647 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   4.648 +    GNU General Public License for more details.
   4.649 +
   4.650 +    You should have received a copy of the GNU General Public License
   4.651 +    along with this program.  If not, see <http://www.gnu.org/licenses/>.
   4.652 +
   4.653 +Also add information on how to contact you by electronic and paper mail.
   4.654 +
   4.655 +  If the program does terminal interaction, make it output a short
   4.656 +notice like this when it starts in an interactive mode:
   4.657 +
   4.658 +    <program>  Copyright (C) <year>  <name of author>
   4.659 +    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
   4.660 +    This is free software, and you are welcome to redistribute it
   4.661 +    under certain conditions; type `show c' for details.
   4.662 +
   4.663 +The hypothetical commands `show w' and `show c' should show the appropriate
   4.664 +parts of the General Public License.  Of course, your program's commands
   4.665 +might be different; for a GUI interface, you would use an "about box".
   4.666 +
   4.667 +  You should also get your employer (if you work as a programmer) or school,
   4.668 +if any, to sign a "copyright disclaimer" for the program, if necessary.
   4.669 +For more information on this, and how to apply and follow the GNU GPL, see
   4.670 +<http://www.gnu.org/licenses/>.
   4.671 +
   4.672 +  The GNU General Public License does not permit incorporating your program
   4.673 +into proprietary programs.  If your program is a subroutine library, you
   4.674 +may consider it more useful to permit linking proprietary applications with
   4.675 +the library.  If this is what you want to do, use the GNU Lesser General
   4.676 +Public License instead of this License.  But first, please read
   4.677 +<http://www.gnu.org/philosophy/why-not-lgpl.html>.
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/hidapi/LICENSE-orig.txt	Thu Aug 09 16:05:48 2018 -0700
     5.3 @@ -0,0 +1,9 @@
     5.4 + HIDAPI - Multi-Platform library for
     5.5 + communication with HID devices.
     5.6 +
     5.7 + Copyright 2009, Alan Ott, Signal 11 Software.
     5.8 + All Rights Reserved.
     5.9 + 
    5.10 + This software may be used by anyone for any reason so
    5.11 + long as the copyright notice in the source files
    5.12 + remains intact.
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/hidapi/LICENSE.txt	Thu Aug 09 16:05:48 2018 -0700
     6.3 @@ -0,0 +1,13 @@
     6.4 +HIDAPI can be used under one of three licenses.
     6.5 +
     6.6 +1. The GNU General Public License, version 3.0, in LICENSE-gpl3.txt
     6.7 +2. A BSD-Style License, in LICENSE-bsd.txt.
     6.8 +3. The more liberal original HIDAPI license. LICENSE-orig.txt
     6.9 +
    6.10 +The license chosen is at the discretion of the user of HIDAPI. For example:
    6.11 +1. An author of GPL software would likely use HIDAPI under the terms of the
    6.12 +GPL.
    6.13 +
    6.14 +2. An author of commercial closed-source software would likely use HIDAPI
    6.15 +under the terms of the BSD-style license or the original HIDAPI license.
    6.16 +
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/hidapi/Makefile.am	Thu Aug 09 16:05:48 2018 -0700
     7.3 @@ -0,0 +1,85 @@
     7.4 +
     7.5 +ACLOCAL_AMFLAGS = -I m4
     7.6 +
     7.7 +if OS_FREEBSD
     7.8 +pkgconfigdir=$(prefix)/libdata/pkgconfig
     7.9 +else
    7.10 +pkgconfigdir=$(libdir)/pkgconfig
    7.11 +endif
    7.12 +
    7.13 +if OS_LINUX
    7.14 +pkgconfig_DATA=pc/hidapi-hidraw.pc pc/hidapi-libusb.pc
    7.15 +else
    7.16 +pkgconfig_DATA=pc/hidapi.pc
    7.17 +endif
    7.18 +
    7.19 +SUBDIRS=
    7.20 +
    7.21 +if OS_LINUX
    7.22 +SUBDIRS += linux libusb
    7.23 +endif
    7.24 +
    7.25 +if OS_DARWIN
    7.26 +SUBDIRS += mac
    7.27 +endif
    7.28 +
    7.29 +if OS_IOS
    7.30 +SUBDIRS += ios
    7.31 +endif
    7.32 +
    7.33 +if OS_FREEBSD
    7.34 +SUBDIRS += libusb
    7.35 +endif
    7.36 +
    7.37 +if OS_KFREEBSD
    7.38 +SUBDIRS += libusb
    7.39 +endif
    7.40 +
    7.41 +if OS_WINDOWS
    7.42 +SUBDIRS += windows
    7.43 +endif
    7.44 +
    7.45 +SUBDIRS += hidtest
    7.46 +
    7.47 +if BUILD_TESTGUI
    7.48 +SUBDIRS += testgui
    7.49 +endif
    7.50 +
    7.51 +EXTRA_DIST = udev doxygen
    7.52 +
    7.53 +dist_doc_DATA = \
    7.54 + README.txt \
    7.55 + AUTHORS.txt \
    7.56 + LICENSE-bsd.txt \
    7.57 + LICENSE-gpl3.txt \
    7.58 + LICENSE-orig.txt \
    7.59 + LICENSE.txt
    7.60 +
    7.61 +SCMCLEAN_TARGETS= \
    7.62 + aclocal.m4 \
    7.63 + config.guess \
    7.64 + config.sub \
    7.65 + configure \
    7.66 + config.h.in \
    7.67 + depcomp \
    7.68 + install-sh \
    7.69 + ltmain.sh \
    7.70 + missing \
    7.71 + mac/Makefile.in \
    7.72 + testgui/Makefile.in \
    7.73 + libusb/Makefile.in \
    7.74 + Makefile.in \
    7.75 + linux/Makefile.in \
    7.76 + windows/Makefile.in \
    7.77 + m4/libtool.m4 \
    7.78 + m4/lt~obsolete.m4 \
    7.79 + m4/ltoptions.m4 \
    7.80 + m4/ltsugar.m4 \
    7.81 + m4/ltversion.m4
    7.82 +
    7.83 +SCMCLEAN_DIR_TARGETS = \
    7.84 + autom4te.cache
    7.85 +
    7.86 +scm-clean: distclean
    7.87 +	rm -f $(SCMCLEAN_TARGETS)
    7.88 +	rm -Rf $(SCMCLEAN_DIR_TARGETS)
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/hidapi/README.txt	Thu Aug 09 16:05:48 2018 -0700
     8.3 @@ -0,0 +1,339 @@
     8.4 +         HIDAPI library for Windows, Linux, FreeBSD and Mac OS X
     8.5 +        =========================================================
     8.6 +
     8.7 +About
     8.8 +======
     8.9 +
    8.10 +HIDAPI is a multi-platform library which allows an application to interface
    8.11 +with USB and Bluetooth HID-Class devices on Windows, Linux, FreeBSD, and Mac
    8.12 +OS X.  HIDAPI can be either built as a shared library (.so or .dll) or
    8.13 +can be embedded directly into a target application by adding a single source
    8.14 +file (per platform) and a single header.
    8.15 +
    8.16 +HIDAPI has four back-ends:
    8.17 +	* Windows (using hid.dll)
    8.18 +	* Linux/hidraw (using the Kernel's hidraw driver)
    8.19 +	* Linux/libusb (using libusb-1.0)
    8.20 +	* FreeBSD (using libusb-1.0)
    8.21 +	* Mac (using IOHidManager)
    8.22 +
    8.23 +On Linux, either the hidraw or the libusb back-end can be used. There are
    8.24 +tradeoffs, and the functionality supported is slightly different.
    8.25 +
    8.26 +Linux/hidraw (linux/hid.c):
    8.27 +This back-end uses the hidraw interface in the Linux kernel.  While this
    8.28 +back-end will support both USB and Bluetooth, it has some limitations on
    8.29 +kernels prior to 2.6.39, including the inability to send or receive feature
    8.30 +reports.  In addition, it will only communicate with devices which have
    8.31 +hidraw nodes associated with them.  Keyboards, mice, and some other devices
    8.32 +which are blacklisted from having hidraw nodes will not work. Fortunately,
    8.33 +for nearly all the uses of hidraw, this is not a problem.
    8.34 +
    8.35 +Linux/FreeBSD/libusb (libusb/hid.c):
    8.36 +This back-end uses libusb-1.0 to communicate directly to a USB device. This
    8.37 +back-end will of course not work with Bluetooth devices.
    8.38 +
    8.39 +HIDAPI also comes with a Test GUI. The Test GUI is cross-platform and uses
    8.40 +Fox Toolkit (http://www.fox-toolkit.org).  It will build on every platform
    8.41 +which HIDAPI supports.  Since it relies on a 3rd party library, building it
    8.42 +is optional but recommended because it is so useful when debugging hardware.
    8.43 +
    8.44 +What Does the API Look Like?
    8.45 +=============================
    8.46 +The API provides the the most commonly used HID functions including sending
    8.47 +and receiving of input, output, and feature reports.  The sample program,
    8.48 +which communicates with a heavily hacked up version of the Microchip USB
    8.49 +Generic HID sample looks like this (with error checking removed for
    8.50 +simplicity):
    8.51 +
    8.52 +#ifdef WIN32
    8.53 +#include <windows.h>
    8.54 +#endif
    8.55 +#include <stdio.h>
    8.56 +#include <stdlib.h>
    8.57 +#include "hidapi.h"
    8.58 +
    8.59 +#define MAX_STR 255
    8.60 +
    8.61 +int main(int argc, char* argv[])
    8.62 +{
    8.63 +	int res;
    8.64 +	unsigned char buf[65];
    8.65 +	wchar_t wstr[MAX_STR];
    8.66 +	hid_device *handle;
    8.67 +	int i;
    8.68 +
    8.69 +	// Initialize the hidapi library
    8.70 +	res = hid_init();
    8.71 +
    8.72 +	// Open the device using the VID, PID,
    8.73 +	// and optionally the Serial number.
    8.74 +	handle = hid_open(0x4d8, 0x3f, NULL);
    8.75 +
    8.76 +	// Read the Manufacturer String
    8.77 +	res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
    8.78 +	wprintf(L"Manufacturer String: %s\n", wstr);
    8.79 +
    8.80 +	// Read the Product String
    8.81 +	res = hid_get_product_string(handle, wstr, MAX_STR);
    8.82 +	wprintf(L"Product String: %s\n", wstr);
    8.83 +
    8.84 +	// Read the Serial Number String
    8.85 +	res = hid_get_serial_number_string(handle, wstr, MAX_STR);
    8.86 +	wprintf(L"Serial Number String: (%d) %s\n", wstr[0], wstr);
    8.87 +
    8.88 +	// Read Indexed String 1
    8.89 +	res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
    8.90 +	wprintf(L"Indexed String 1: %s\n", wstr);
    8.91 +
    8.92 +	// Toggle LED (cmd 0x80). The first byte is the report number (0x0).
    8.93 +	buf[0] = 0x0;
    8.94 +	buf[1] = 0x80;
    8.95 +	res = hid_write(handle, buf, 65);
    8.96 +
    8.97 +	// Request state (cmd 0x81). The first byte is the report number (0x0).
    8.98 +	buf[0] = 0x0;
    8.99 +	buf[1] = 0x81;
   8.100 +	res = hid_write(handle, buf, 65);
   8.101 +
   8.102 +	// Read requested state
   8.103 +	res = hid_read(handle, buf, 65);
   8.104 +
   8.105 +	// Print out the returned buffer.
   8.106 +	for (i = 0; i < 4; i++)
   8.107 +		printf("buf[%d]: %d\n", i, buf[i]);
   8.108 +
   8.109 +	// Finalize the hidapi library
   8.110 +	res = hid_exit();
   8.111 +
   8.112 +	return 0;
   8.113 +}
   8.114 +
   8.115 +If you have your own simple test programs which communicate with standard
   8.116 +hardware development boards (such as those from Microchip, TI, Atmel,
   8.117 +FreeScale and others), please consider sending me something like the above
   8.118 +for inclusion into the HIDAPI source.  This will help others who have the
   8.119 +same hardware as you do.
   8.120 +
   8.121 +License
   8.122 +========
   8.123 +HIDAPI may be used by one of three licenses as outlined in LICENSE.txt.
   8.124 +
   8.125 +Download
   8.126 +=========
   8.127 +HIDAPI can be downloaded from github
   8.128 +	git clone git://github.com/signal11/hidapi.git
   8.129 +
   8.130 +Build Instructions
   8.131 +===================
   8.132 +
   8.133 +This section is long. Don't be put off by this. It's not long because it's
   8.134 +complicated to build HIDAPI; it's quite the opposite.  This section is long
   8.135 +because of the flexibility of HIDAPI and the large number of ways in which
   8.136 +it can be built and used.  You will likely pick a single build method.
   8.137 +
   8.138 +HIDAPI can be built in several different ways. If you elect to build a
   8.139 +shared library, you will need to build it from the HIDAPI source
   8.140 +distribution.  If you choose instead to embed HIDAPI directly into your
   8.141 +application, you can skip the building and look at the provided platform
   8.142 +Makefiles for guidance.  These platform Makefiles are located in linux/
   8.143 +libusb/ mac/ and windows/ and are called Makefile-manual.  In addition,
   8.144 +Visual Studio projects are provided.  Even if you're going to embed HIDAPI
   8.145 +into your project, it is still beneficial to build the example programs.
   8.146 +
   8.147 +
   8.148 +Prerequisites:
   8.149 +---------------
   8.150 +
   8.151 +	Linux:
   8.152 +	-------
   8.153 +	On Linux, you will need to install development packages for libudev,
   8.154 +	libusb and optionally Fox-toolkit (for the test GUI). On
   8.155 +	Debian/Ubuntu systems these can be installed by running:
   8.156 +	    sudo apt-get install libudev-dev libusb-1.0-0-dev libfox-1.6-dev
   8.157 +
   8.158 +	If you downloaded the source directly from the git repository (using
   8.159 +	git clone), you'll need Autotools:
   8.160 +	    sudo apt-get install autotools-dev autoconf automake libtool
   8.161 +
   8.162 +	FreeBSD:
   8.163 +	---------
   8.164 +	On FreeBSD you will need to install GNU make, libiconv, and
   8.165 +	optionally Fox-Toolkit (for the test GUI). This is done by running
   8.166 +	the following:
   8.167 +	    pkg_add -r gmake libiconv fox16
   8.168 +
   8.169 +	If you downloaded the source directly from the git repository (using
   8.170 +	git clone), you'll need Autotools:
   8.171 +	    pkg_add -r autotools
   8.172 +
   8.173 +	Mac:
   8.174 +	-----
   8.175 +	On Mac, you will need to install Fox-Toolkit if you wish to build
   8.176 +	the Test GUI. There are two ways to do this, and each has a slight
   8.177 +	complication. Which method you use depends on your use case.
   8.178 +
   8.179 +	If you wish to build the Test GUI just for your own testing on your
   8.180 +	own computer, then the easiest method is to install Fox-Toolkit
   8.181 +	using ports:
   8.182 +		sudo port install fox
   8.183 +
   8.184 +	If you wish to build the TestGUI app bundle to redistribute to
   8.185 +	others, you will need to install Fox-toolkit from source.  This is
   8.186 +	because the version of fox that gets installed using ports uses the
   8.187 +	ports X11 libraries which are not compatible with the Apple X11
   8.188 +	libraries.  If you install Fox with ports and then try to distribute
   8.189 +	your built app bundle, it will simply fail to run on other systems.
   8.190 +	To install Fox-Toolkit manually, download the source package from
   8.191 +	http://www.fox-toolkit.org, extract it, and run the following from
   8.192 +	within the extracted source:
   8.193 +		./configure && make && make install
   8.194 +
   8.195 +	Windows:
   8.196 +	---------
   8.197 +	On Windows, if you want to build the test GUI, you will need to get
   8.198 +	the hidapi-externals.zip package from the download site.  This
   8.199 +	contains pre-built binaries for Fox-toolkit.  Extract
   8.200 +	hidapi-externals.zip just outside of hidapi, so that
   8.201 +	hidapi-externals and hidapi are on the same level, as shown:
   8.202 +
   8.203 +	     Parent_Folder
   8.204 +	       |
   8.205 +	       +hidapi
   8.206 +	       +hidapi-externals
   8.207 +
   8.208 +	Again, this step is not required if you do not wish to build the
   8.209 +	test GUI.
   8.210 +
   8.211 +
   8.212 +Building HIDAPI into a shared library on Unix Platforms:
   8.213 +---------------------------------------------------------
   8.214 +
   8.215 +On Unix-like systems such as Linux, FreeBSD, Mac, and even Windows, using
   8.216 +Mingw or Cygwin, the easiest way to build a standard system-installed shared
   8.217 +library is to use the GNU Autotools build system.  If you checked out the
   8.218 +source from the git repository, run the following:
   8.219 +
   8.220 +	./bootstrap
   8.221 +	./configure
   8.222 +	make
   8.223 +	make install     <----- as root, or using sudo
   8.224 +
   8.225 +If you downloaded a source package (ie: if you did not run git clone), you
   8.226 +can skip the ./bootstrap step.
   8.227 +
   8.228 +./configure can take several arguments which control the build. The two most
   8.229 +likely to be used are:
   8.230 +	--enable-testgui
   8.231 +		Enable build of the Test GUI. This requires Fox toolkit to
   8.232 +		be installed.  Instructions for installing Fox-Toolkit on
   8.233 +		each platform are in the Prerequisites section above.
   8.234 +
   8.235 +	--prefix=/usr
   8.236 +		Specify where you want the output headers and libraries to
   8.237 +		be installed. The example above will put the headers in
   8.238 +		/usr/include and the binaries in /usr/lib. The default is to
   8.239 +		install into /usr/local which is fine on most systems.
   8.240 +
   8.241 +Building the manual way on Unix platforms:
   8.242 +-------------------------------------------
   8.243 +
   8.244 +Manual Makefiles are provided mostly to give the user and idea what it takes
   8.245 +to build a program which embeds HIDAPI directly inside of it. These should
   8.246 +really be used as examples only. If you want to build a system-wide shared
   8.247 +library, use the Autotools method described above.
   8.248 +
   8.249 +	To build HIDAPI using the manual makefiles, change to the directory
   8.250 +	of your platform and run make. For example, on Linux run:
   8.251 +		cd linux/
   8.252 +		make -f Makefile-manual
   8.253 +
   8.254 +	To build the Test GUI using the manual makefiles:
   8.255 +		cd testgui/
   8.256 +		make -f Makefile-manual
   8.257 +
   8.258 +Building on Windows:
   8.259 +---------------------
   8.260 +
   8.261 +To build the HIDAPI DLL on Windows using Visual Studio, build the .sln file
   8.262 +in the windows/ directory.
   8.263 +
   8.264 +To build the Test GUI on windows using Visual Studio, build the .sln file in
   8.265 +the testgui/ directory.
   8.266 +
   8.267 +To build HIDAPI using MinGW or Cygwin using Autotools, use the instructions
   8.268 +in the section titled "Building HIDAPI into a shared library on Unix
   8.269 +Platforms" above.  Note that building the Test GUI with MinGW or Cygwin will
   8.270 +require the Windows procedure in the Prerequisites section above (ie:
   8.271 +hidapi-externals.zip).
   8.272 +
   8.273 +To build HIDAPI using MinGW using the Manual Makefiles, see the section
   8.274 +"Building the manual way on Unix platforms" above.
   8.275 +
   8.276 +HIDAPI can also be built using the Windows DDK (now also called the Windows
   8.277 +Driver Kit or WDK). This method was originally required for the HIDAPI build
   8.278 +but not anymore. However, some users still prefer this method. It is not as
   8.279 +well supported anymore but should still work. Patches are welcome if it does
   8.280 +not. To build using the DDK:
   8.281 +
   8.282 +   1. Install the Windows Driver Kit (WDK) from Microsoft.
   8.283 +   2. From the Start menu, in the Windows Driver Kits folder, select Build
   8.284 +      Environments, then your operating system, then the x86 Free Build
   8.285 +      Environment (or one that is appropriate for your system).
   8.286 +   3. From the console, change directory to the windows/ddk_build/ directory,
   8.287 +      which is part of the HIDAPI distribution.
   8.288 +   4. Type build.
   8.289 +   5. You can find the output files (DLL and LIB) in a subdirectory created
   8.290 +      by the build system which is appropriate for your environment. On
   8.291 +      Windows XP, this directory is objfre_wxp_x86/i386.
   8.292 +
   8.293 +Cross Compiling
   8.294 +================
   8.295 +
   8.296 +This section talks about cross compiling HIDAPI for Linux using autotools.
   8.297 +This is useful for using HIDAPI on embedded Linux targets.  These
   8.298 +instructions assume the most raw kind of embedded Linux build, where all
   8.299 +prerequisites will need to be built first.  This process will of course vary
   8.300 +based on your embedded Linux build system if you are using one, such as
   8.301 +OpenEmbedded or Buildroot.
   8.302 +
   8.303 +For the purpose of this section, it will be assumed that the following
   8.304 +environment variables are exported.
   8.305 +
   8.306 +	$ export STAGING=$HOME/out
   8.307 +	$ export HOST=arm-linux
   8.308 +
   8.309 +STAGING and HOST can be modified to suit your setup.
   8.310 +
   8.311 +Prerequisites
   8.312 +--------------
   8.313 +
   8.314 +Note that the build of libudev is the very basic configuration.
   8.315 +
   8.316 +Build Libusb. From the libusb source directory, run:
   8.317 +	./configure --host=$HOST --prefix=$STAGING
   8.318 +	make
   8.319 +	make install
   8.320 +
   8.321 +Build libudev. From the libudev source directory, run:
   8.322 +	./configure --disable-gudev --disable-introspection --disable-hwdb \
   8.323 +		 --host=$HOST --prefix=$STAGING
   8.324 +	make
   8.325 +	make install
   8.326 +
   8.327 +Building HIDAPI
   8.328 +----------------
   8.329 +
   8.330 +Build HIDAPI:
   8.331 +
   8.332 +	PKG_CONFIG_DIR= \
   8.333 +	PKG_CONFIG_LIBDIR=$STAGING/lib/pkgconfig:$STAGING/share/pkgconfig \
   8.334 +	PKG_CONFIG_SYSROOT_DIR=$STAGING \
   8.335 +	./configure --host=$HOST --prefix=$STAGING
   8.336 +
   8.337 +
   8.338 +Signal 11 Software - 2010-04-11
   8.339 +                     2010-07-28
   8.340 +                     2011-09-10
   8.341 +                     2012-05-01
   8.342 +                     2012-07-03
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/hidapi/android/hid.cpp	Thu Aug 09 16:05:48 2018 -0700
     9.3 @@ -0,0 +1,1078 @@
     9.4 +//=================== Copyright Valve Corporation, All rights reserved. =======
     9.5 +//
     9.6 +// Purpose: A wrapper implementing "HID" API for Android
     9.7 +//
     9.8 +//          This layer glues the hidapi API to Android's USB and BLE stack.
     9.9 +//
    9.10 +//=============================================================================
    9.11 +
    9.12 +#include <jni.h>
    9.13 +#include <android/log.h>
    9.14 +#include <pthread.h>
    9.15 +#include <errno.h>	// For ETIMEDOUT and ECONNRESET
    9.16 +
    9.17 +#define TAG "hidapi"
    9.18 +#ifdef DEBUG
    9.19 +#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
    9.20 +#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
    9.21 +#else
    9.22 +#define LOGV(...)
    9.23 +#define LOGD(...)
    9.24 +#endif
    9.25 +
    9.26 +#define SDL_JAVA_PREFIX                                 org_libsdl_app
    9.27 +#define CONCAT1(prefix, class, function)                CONCAT2(prefix, class, function)
    9.28 +#define CONCAT2(prefix, class, function)                Java_ ## prefix ## _ ## class ## _ ## function
    9.29 +#define HID_DEVICE_MANAGER_JAVA_INTERFACE(function)     CONCAT1(SDL_JAVA_PREFIX, HIDDeviceManager, function)
    9.30 +
    9.31 +#include "../hidapi/hidapi.h"
    9.32 +typedef uint32_t uint32;
    9.33 +typedef uint64_t uint64;
    9.34 +
    9.35 +
    9.36 +struct hid_device_
    9.37 +{
    9.38 +	int nId;
    9.39 +};
    9.40 +
    9.41 +static JavaVM *g_JVM;
    9.42 +static pthread_key_t g_ThreadKey;
    9.43 +
    9.44 +template<class T>
    9.45 +class hid_device_ref
    9.46 +{
    9.47 +public:
    9.48 +	hid_device_ref( T *pObject = nullptr ) : m_pObject( nullptr )
    9.49 +	{
    9.50 +		SetObject( pObject );
    9.51 +	}
    9.52 +
    9.53 +	hid_device_ref( const hid_device_ref &rhs ) : m_pObject( nullptr )
    9.54 +	{
    9.55 +		SetObject( rhs.GetObject() );
    9.56 +	}
    9.57 +
    9.58 +	~hid_device_ref()
    9.59 +	{
    9.60 +		SetObject( nullptr );
    9.61 +	}
    9.62 +
    9.63 +	void SetObject( T *pObject )
    9.64 +	{
    9.65 +		if ( m_pObject && m_pObject->DecrementRefCount() == 0 )
    9.66 +		{
    9.67 +			delete m_pObject;
    9.68 +		}
    9.69 +
    9.70 +		m_pObject = pObject;
    9.71 +
    9.72 +		if ( m_pObject )
    9.73 +		{
    9.74 +			m_pObject->IncrementRefCount();
    9.75 +		}
    9.76 +	}
    9.77 +
    9.78 +	hid_device_ref &operator =( T *pObject )
    9.79 +	{
    9.80 +		SetObject( pObject );
    9.81 +		return *this;
    9.82 +	}
    9.83 +
    9.84 +	hid_device_ref &operator =( const hid_device_ref &rhs )
    9.85 +	{
    9.86 +		SetObject( rhs.GetObject() );
    9.87 +		return *this;
    9.88 +	}
    9.89 +
    9.90 +	T *GetObject() const
    9.91 +	{
    9.92 +		return m_pObject;
    9.93 +	}
    9.94 +
    9.95 +	T* operator->() const
    9.96 +	{
    9.97 +		return m_pObject;
    9.98 +	}
    9.99 +
   9.100 +	operator bool() const
   9.101 +	{
   9.102 +		return ( m_pObject != nullptr );
   9.103 +	}
   9.104 +
   9.105 +private:
   9.106 +	T *m_pObject;
   9.107 +};
   9.108 +
   9.109 +class hid_mutex_guard
   9.110 +{
   9.111 +public:
   9.112 +	hid_mutex_guard( pthread_mutex_t *pMutex ) : m_pMutex( pMutex )
   9.113 +	{
   9.114 +		pthread_mutex_lock( m_pMutex );
   9.115 +	}
   9.116 +	~hid_mutex_guard()
   9.117 +	{
   9.118 +		pthread_mutex_unlock( m_pMutex );
   9.119 +	}
   9.120 +
   9.121 +private:
   9.122 +	pthread_mutex_t *m_pMutex;
   9.123 +};
   9.124 +
   9.125 +class hid_buffer
   9.126 +{
   9.127 +public:
   9.128 +	hid_buffer() : m_pData( nullptr ), m_nSize( 0 ), m_nAllocated( 0 )
   9.129 +	{
   9.130 +	}
   9.131 +
   9.132 +	hid_buffer( const uint8_t *pData, size_t nSize ) : m_pData( nullptr ), m_nSize( 0 ), m_nAllocated( 0 )
   9.133 +	{
   9.134 +		assign( pData, nSize );
   9.135 +	}
   9.136 +
   9.137 +	~hid_buffer()
   9.138 +	{
   9.139 +		delete[] m_pData;
   9.140 +	}
   9.141 +
   9.142 +	void assign( const uint8_t *pData, size_t nSize )
   9.143 +	{
   9.144 +		if ( nSize > m_nAllocated )
   9.145 +		{
   9.146 +			delete[] m_pData;
   9.147 +			m_pData = new uint8_t[ nSize ];
   9.148 +			m_nAllocated = nSize;
   9.149 +		}
   9.150 +
   9.151 +		m_nSize = nSize;
   9.152 +		memcpy( m_pData, pData, nSize );
   9.153 +	}
   9.154 +
   9.155 +	void clear()
   9.156 +	{
   9.157 +		m_nSize = 0;
   9.158 +	}
   9.159 +
   9.160 +	size_t size() const
   9.161 +	{
   9.162 +		return m_nSize;
   9.163 +	}
   9.164 +
   9.165 +	const uint8_t *data() const
   9.166 +	{
   9.167 +		return m_pData;
   9.168 +	}
   9.169 +
   9.170 +private:
   9.171 +	uint8_t *m_pData;
   9.172 +	size_t m_nSize;
   9.173 +	size_t m_nAllocated;
   9.174 +};
   9.175 +
   9.176 +class hid_buffer_pool
   9.177 +{
   9.178 +public:
   9.179 +	hid_buffer_pool() : m_nSize( 0 ), m_pHead( nullptr ), m_pTail( nullptr ), m_pFree( nullptr )
   9.180 +	{
   9.181 +	}
   9.182 +
   9.183 +	~hid_buffer_pool()
   9.184 +	{
   9.185 +		clear();
   9.186 +
   9.187 +		while ( m_pFree )
   9.188 +		{
   9.189 +			hid_buffer_entry *pEntry = m_pFree;
   9.190 +			m_pFree = m_pFree->m_pNext;
   9.191 +			delete pEntry;
   9.192 +		}
   9.193 +	}
   9.194 +
   9.195 +	size_t size() const { return m_nSize; }
   9.196 +
   9.197 +	const hid_buffer &front() const { return m_pHead->m_buffer; }
   9.198 +
   9.199 +	void pop_front()
   9.200 +	{
   9.201 +		hid_buffer_entry *pEntry = m_pHead;
   9.202 +		if ( pEntry )
   9.203 +		{
   9.204 +			m_pHead = pEntry->m_pNext;
   9.205 +			if ( !m_pHead )
   9.206 +			{
   9.207 +				m_pTail = nullptr;
   9.208 +			}
   9.209 +			pEntry->m_pNext = m_pFree;
   9.210 +			m_pFree = pEntry;
   9.211 +			--m_nSize;
   9.212 +		}
   9.213 +	}
   9.214 +
   9.215 +	void emplace_back( const uint8_t *pData, size_t nSize )
   9.216 +	{
   9.217 +		hid_buffer_entry *pEntry;
   9.218 +
   9.219 +		if ( m_pFree )
   9.220 +		{
   9.221 +			pEntry = m_pFree;
   9.222 +			m_pFree = m_pFree->m_pNext;
   9.223 +		}
   9.224 +		else
   9.225 +		{
   9.226 +			pEntry = new hid_buffer_entry;
   9.227 +		}
   9.228 +		pEntry->m_pNext = nullptr;
   9.229 +
   9.230 +		if ( m_pTail )
   9.231 +		{
   9.232 +			m_pTail->m_pNext = pEntry;
   9.233 +		}
   9.234 +		else
   9.235 +		{
   9.236 +			m_pHead = pEntry;
   9.237 +		}
   9.238 +		m_pTail = pEntry;
   9.239 +
   9.240 +		pEntry->m_buffer.assign( pData, nSize );
   9.241 +		++m_nSize;
   9.242 +	}
   9.243 +
   9.244 +	void clear()
   9.245 +	{
   9.246 +		while ( size() > 0 )
   9.247 +		{
   9.248 +			pop_front();
   9.249 +		}
   9.250 +	}
   9.251 +
   9.252 +private:
   9.253 +	struct hid_buffer_entry
   9.254 +	{
   9.255 +		hid_buffer m_buffer;
   9.256 +		hid_buffer_entry *m_pNext;
   9.257 +	};
   9.258 +
   9.259 +	size_t m_nSize;
   9.260 +	hid_buffer_entry *m_pHead;
   9.261 +	hid_buffer_entry *m_pTail;
   9.262 +	hid_buffer_entry *m_pFree;
   9.263 +};
   9.264 +
   9.265 +static jbyteArray NewByteArray( JNIEnv* env, const uint8_t *pData, size_t nDataLen )
   9.266 +{
   9.267 +	jbyteArray array = env->NewByteArray( nDataLen );
   9.268 +	jbyte *pBuf = env->GetByteArrayElements( array, NULL );
   9.269 +	memcpy( pBuf, pData, nDataLen );
   9.270 +	env->ReleaseByteArrayElements( array, pBuf, 0 );
   9.271 +
   9.272 +	return array;
   9.273 +}
   9.274 +
   9.275 +static char *CreateStringFromJString( JNIEnv *env, const jstring &sString )
   9.276 +{
   9.277 +	size_t nLength = env->GetStringUTFLength( sString );
   9.278 +	const char *pjChars = env->GetStringUTFChars( sString, NULL );
   9.279 +	char *psString = (char*)malloc( nLength + 1 );
   9.280 +	memcpy( psString, pjChars, nLength );
   9.281 +	psString[ nLength ] = '\0';
   9.282 +	env->ReleaseStringUTFChars( sString, pjChars );
   9.283 +	return psString;
   9.284 +}
   9.285 +
   9.286 +static wchar_t *CreateWStringFromJString( JNIEnv *env, const jstring &sString )
   9.287 +{
   9.288 +	size_t nLength = env->GetStringLength( sString );
   9.289 +	const jchar *pjChars = env->GetStringChars( sString, NULL );
   9.290 +	wchar_t *pwString = (wchar_t*)malloc( ( nLength + 1 ) * sizeof( wchar_t ) );
   9.291 +	wchar_t *pwChars = pwString;
   9.292 +	for ( size_t iIndex = 0; iIndex < nLength; ++iIndex )
   9.293 +	{
   9.294 +		pwChars[ iIndex ] = pjChars[ iIndex ];
   9.295 +	}
   9.296 +	pwString[ nLength ] = '\0';
   9.297 +	env->ReleaseStringChars( sString, pjChars );
   9.298 +	return pwString;
   9.299 +}
   9.300 +
   9.301 +static wchar_t *CreateWStringFromWString( const wchar_t *pwSrc )
   9.302 +{
   9.303 +	size_t nLength = wcslen( pwSrc );
   9.304 +	wchar_t *pwString = (wchar_t*)malloc( ( nLength + 1 ) * sizeof( wchar_t ) );
   9.305 +	memcpy( pwString, pwSrc, nLength * sizeof( wchar_t ) );
   9.306 +	pwString[ nLength ] = '\0';
   9.307 +	return pwString;
   9.308 +}
   9.309 +
   9.310 +static hid_device_info *CopyHIDDeviceInfo( const hid_device_info *pInfo )
   9.311 +{
   9.312 +	hid_device_info *pCopy = new hid_device_info;
   9.313 +	*pCopy = *pInfo;
   9.314 +	pCopy->path = strdup( pInfo->path );
   9.315 +	pCopy->product_string = CreateWStringFromWString( pInfo->product_string );
   9.316 +	pCopy->manufacturer_string = CreateWStringFromWString( pInfo->manufacturer_string );
   9.317 +	pCopy->serial_number = CreateWStringFromWString( pInfo->serial_number );
   9.318 +	return pCopy;
   9.319 +}
   9.320 +
   9.321 +static void FreeHIDDeviceInfo( hid_device_info *pInfo )
   9.322 +{
   9.323 +	free( pInfo->path );
   9.324 +	free( pInfo->serial_number );
   9.325 +	free( pInfo->manufacturer_string );
   9.326 +	free( pInfo->product_string );
   9.327 +	delete pInfo;
   9.328 +}
   9.329 +
   9.330 +static jclass  g_HIDDeviceManagerCallbackClass;
   9.331 +static jobject g_HIDDeviceManagerCallbackHandler;
   9.332 +static jmethodID g_midHIDDeviceManagerOpen;
   9.333 +static jmethodID g_midHIDDeviceManagerSendOutputReport;
   9.334 +static jmethodID g_midHIDDeviceManagerSendFeatureReport;
   9.335 +static jmethodID g_midHIDDeviceManagerGetFeatureReport;
   9.336 +static jmethodID g_midHIDDeviceManagerClose;
   9.337 +
   9.338 +uint64_t get_timespec_ms( const struct timespec &ts )
   9.339 +{
   9.340 +	return (uint64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
   9.341 +}
   9.342 +
   9.343 +class CHIDDevice
   9.344 +{
   9.345 +public:
   9.346 +	CHIDDevice( int nDeviceID, hid_device_info *pInfo )
   9.347 +	{
   9.348 +		m_nId = nDeviceID;
   9.349 +		m_pInfo = pInfo;
   9.350 +
   9.351 +		// The Bluetooth Steam Controller needs special handling
   9.352 +		const int VALVE_USB_VID	= 0x28DE;
   9.353 +		const int D0G_BLE2_PID = 0x1106;
   9.354 +		if ( pInfo->vendor_id == VALVE_USB_VID && pInfo->product_id == D0G_BLE2_PID )
   9.355 +		{
   9.356 +			m_bIsBLESteamController = true;
   9.357 +		}
   9.358 +	}
   9.359 +
   9.360 +	~CHIDDevice()
   9.361 +	{
   9.362 +		FreeHIDDeviceInfo( m_pInfo );
   9.363 +
   9.364 +		// Note that we don't delete m_pDevice, as the app may still have a reference to it
   9.365 +	}
   9.366 +
   9.367 +	int IncrementRefCount()
   9.368 +	{
   9.369 +		return ++m_nRefCount;
   9.370 +	}
   9.371 +
   9.372 +	int DecrementRefCount()
   9.373 +	{
   9.374 +		return --m_nRefCount;
   9.375 +	}
   9.376 +
   9.377 +	int GetId()
   9.378 +	{
   9.379 +		return m_nId;
   9.380 +	}
   9.381 +
   9.382 +	const hid_device_info *GetDeviceInfo()
   9.383 +	{
   9.384 +		return m_pInfo;
   9.385 +	}
   9.386 +
   9.387 +	hid_device *GetDevice()
   9.388 +	{
   9.389 +		return m_pDevice;
   9.390 +	}
   9.391 +
   9.392 +	int GetDeviceRefCount()
   9.393 +	{
   9.394 +		return m_nDeviceRefCount;
   9.395 +	}
   9.396 +
   9.397 +	int IncrementDeviceRefCount()
   9.398 +	{
   9.399 +		return ++m_nDeviceRefCount;
   9.400 +	}
   9.401 +
   9.402 +	int DecrementDeviceRefCount()
   9.403 +	{
   9.404 +		return --m_nDeviceRefCount;
   9.405 +	}
   9.406 +
   9.407 +	bool BOpen()
   9.408 +	{
   9.409 +		// Make sure thread is attached to JVM/env
   9.410 +		JNIEnv *env;
   9.411 +		g_JVM->AttachCurrentThread( &env, NULL );
   9.412 +		pthread_setspecific( g_ThreadKey, (void*)env );
   9.413 +
   9.414 +		m_bIsWaitingForOpen = false;
   9.415 +		m_bOpenResult = env->CallBooleanMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerOpen, m_nId );
   9.416 +
   9.417 +		if ( m_bIsWaitingForOpen )
   9.418 +		{
   9.419 +			hid_mutex_guard cvl( &m_cvLock );
   9.420 +
   9.421 +			const int OPEN_TIMEOUT_SECONDS = 60;
   9.422 +			struct timespec ts, endtime;
   9.423 +			clock_gettime( CLOCK_REALTIME, &ts );
   9.424 +			endtime = ts;
   9.425 +			endtime.tv_sec += OPEN_TIMEOUT_SECONDS;
   9.426 +			do
   9.427 +			{
   9.428 +				if ( pthread_cond_timedwait( &m_cv, &m_cvLock, &endtime ) != 0 )
   9.429 +				{
   9.430 +					break;
   9.431 +				}
   9.432 +			}
   9.433 +			while ( m_bIsWaitingForOpen && get_timespec_ms( ts ) < get_timespec_ms( endtime ) );
   9.434 +		}
   9.435 +
   9.436 +		if ( !m_bOpenResult )
   9.437 +		{
   9.438 +			if ( m_bIsWaitingForOpen )
   9.439 +			{
   9.440 +				LOGV( "Device open failed - timed out waiting for device permission" );
   9.441 +			}
   9.442 +			else
   9.443 +			{
   9.444 +				LOGV( "Device open failed" );
   9.445 +			}
   9.446 +			return false;
   9.447 +		}
   9.448 +
   9.449 +		m_pDevice = new hid_device;
   9.450 +		m_pDevice->nId = m_nId;
   9.451 +		m_nDeviceRefCount = 1;
   9.452 +		return true;
   9.453 +	}
   9.454 +
   9.455 +	void SetOpenPending()
   9.456 +	{
   9.457 +		m_bIsWaitingForOpen = true;
   9.458 +	}
   9.459 +
   9.460 +	void SetOpenResult( bool bResult )
   9.461 +	{
   9.462 +		if ( m_bIsWaitingForOpen )
   9.463 +		{
   9.464 +			m_bOpenResult = bResult;
   9.465 +			m_bIsWaitingForOpen = false;
   9.466 +			pthread_cond_signal( &m_cv );
   9.467 +		}
   9.468 +	}
   9.469 +
   9.470 +	void ProcessInput( const uint8_t *pBuf, size_t nBufSize )
   9.471 +	{
   9.472 +		hid_mutex_guard l( &m_dataLock );
   9.473 +
   9.474 +		size_t MAX_REPORT_QUEUE_SIZE = 16;
   9.475 +		if ( m_vecData.size() >= MAX_REPORT_QUEUE_SIZE )
   9.476 +		{
   9.477 +			m_vecData.pop_front();
   9.478 +		}
   9.479 +		m_vecData.emplace_back( pBuf, nBufSize );
   9.480 +	}
   9.481 +
   9.482 +	int GetInput( unsigned char *data, size_t length )
   9.483 +	{
   9.484 +		hid_mutex_guard l( &m_dataLock );
   9.485 +
   9.486 +		if ( m_vecData.size() == 0 )
   9.487 +		{
   9.488 +//			LOGV( "hid_read_timeout no data available" );
   9.489 +			return 0;
   9.490 +		}
   9.491 +
   9.492 +		const hid_buffer &buffer = m_vecData.front();
   9.493 +		size_t nDataLen = buffer.size() > length ? length : buffer.size();
   9.494 +		if ( m_bIsBLESteamController )
   9.495 +		{
   9.496 +			data[0] = 0x03;
   9.497 +			memcpy( data + 1, buffer.data(), nDataLen );
   9.498 +			++nDataLen;
   9.499 +		}
   9.500 +		else
   9.501 +		{
   9.502 +			memcpy( data, buffer.data(), nDataLen );
   9.503 +		}
   9.504 +		m_vecData.pop_front();
   9.505 +
   9.506 +//		LOGV("Read %u bytes", nDataLen);
   9.507 +//		LOGV("%02x %02x %02x %02x %02x %02x %02x %02x ....",
   9.508 +//			 data[0], data[1], data[2], data[3],
   9.509 +//			 data[4], data[5], data[6], data[7]);
   9.510 +
   9.511 +		return nDataLen;
   9.512 +	}
   9.513 +
   9.514 +	int SendOutputReport( const unsigned char *pData, size_t nDataLen )
   9.515 +	{
   9.516 +		// Make sure thread is attached to JVM/env
   9.517 +		JNIEnv *env;
   9.518 +		g_JVM->AttachCurrentThread( &env, NULL );
   9.519 +		pthread_setspecific( g_ThreadKey, (void*)env );
   9.520 +
   9.521 +		jbyteArray pBuf = NewByteArray( env, pData, nDataLen );
   9.522 +		int nRet = env->CallIntMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerSendOutputReport, m_nId, pBuf );
   9.523 +		env->DeleteLocalRef( pBuf );
   9.524 +		return nRet;
   9.525 +	}
   9.526 +
   9.527 +	int SendFeatureReport( const unsigned char *pData, size_t nDataLen )
   9.528 +	{
   9.529 +		// Make sure thread is attached to JVM/env
   9.530 +		JNIEnv *env;
   9.531 +		g_JVM->AttachCurrentThread( &env, NULL );
   9.532 +		pthread_setspecific( g_ThreadKey, (void*)env );
   9.533 +
   9.534 +		jbyteArray pBuf = NewByteArray( env, pData, nDataLen );
   9.535 +		int nRet = env->CallIntMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerSendFeatureReport, m_nId, pBuf );
   9.536 +		env->DeleteLocalRef( pBuf );
   9.537 +		return nRet;
   9.538 +	}
   9.539 +
   9.540 +	void ProcessFeatureReport( const uint8_t *pBuf, size_t nBufSize )
   9.541 +	{
   9.542 +		hid_mutex_guard cvl( &m_cvLock );
   9.543 +		if ( m_bIsWaitingForFeatureReport )
   9.544 +		{
   9.545 +			m_featureReport.assign( pBuf, nBufSize );
   9.546 +
   9.547 +			m_bIsWaitingForFeatureReport = false;
   9.548 +			m_nFeatureReportError = 0;
   9.549 +			pthread_cond_signal( &m_cv );
   9.550 +		}
   9.551 +	}
   9.552 +
   9.553 +	int GetFeatureReport( unsigned char *pData, size_t nDataLen )
   9.554 +	{
   9.555 +		// Make sure thread is attached to JVM/env
   9.556 +		JNIEnv *env;
   9.557 +		g_JVM->AttachCurrentThread( &env, NULL );
   9.558 +		pthread_setspecific( g_ThreadKey, (void*)env );
   9.559 +
   9.560 +		{
   9.561 +			hid_mutex_guard cvl( &m_cvLock );
   9.562 +			if ( m_bIsWaitingForFeatureReport )
   9.563 +			{
   9.564 +				LOGV( "Get feature report already ongoing... bail" );
   9.565 +				return -1; // Read already ongoing, we currently do not serialize, TODO
   9.566 +			}
   9.567 +			m_bIsWaitingForFeatureReport = true;
   9.568 +		}
   9.569 +
   9.570 +		jbyteArray pBuf = NewByteArray( env, pData, nDataLen );
   9.571 +		int nRet = env->CallBooleanMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerGetFeatureReport, m_nId, pBuf ) ? 0 : -1;
   9.572 +		env->DeleteLocalRef( pBuf );
   9.573 +		if ( nRet < 0 )
   9.574 +		{
   9.575 +			LOGV( "GetFeatureReport failed" );
   9.576 +			m_bIsWaitingForFeatureReport = false;
   9.577 +			return -1;
   9.578 +		}
   9.579 +
   9.580 +		{
   9.581 +			hid_mutex_guard cvl( &m_cvLock );
   9.582 +			if ( m_bIsWaitingForFeatureReport )
   9.583 +			{
   9.584 +				LOGV("=== Going to sleep" );
   9.585 +				// Wait in CV until we are no longer waiting for a feature report.
   9.586 +				const int FEATURE_REPORT_TIMEOUT_SECONDS = 2;
   9.587 +				struct timespec ts, endtime;
   9.588 +				clock_gettime( CLOCK_REALTIME, &ts );
   9.589 +				endtime = ts;
   9.590 +				endtime.tv_sec += FEATURE_REPORT_TIMEOUT_SECONDS;
   9.591 +				do
   9.592 +				{
   9.593 +					if ( pthread_cond_timedwait( &m_cv, &m_cvLock, &endtime ) != 0 )
   9.594 +					{
   9.595 +						break;
   9.596 +					}
   9.597 +				}
   9.598 +				while ( m_bIsWaitingForFeatureReport && get_timespec_ms( ts ) < get_timespec_ms( endtime ) );
   9.599 +
   9.600 +				// We are back
   9.601 +				if ( m_bIsWaitingForFeatureReport )
   9.602 +				{
   9.603 +					m_nFeatureReportError = -ETIMEDOUT;
   9.604 +					m_bIsWaitingForFeatureReport = false;
   9.605 +				}
   9.606 +				LOGV( "=== Got feature report err=%d", m_nFeatureReportError );
   9.607 +				if ( m_nFeatureReportError != 0 )
   9.608 +				{
   9.609 +					return m_nFeatureReportError;
   9.610 +				}
   9.611 +			}
   9.612 +
   9.613 +			size_t uBytesToCopy = m_featureReport.size() > nDataLen ? nDataLen : m_featureReport.size();
   9.614 +			memcpy( pData, m_featureReport.data(), uBytesToCopy );
   9.615 +			m_featureReport.clear();
   9.616 +			LOGV( "=== Got %u bytes", uBytesToCopy );
   9.617 +
   9.618 +			return uBytesToCopy;
   9.619 +		}
   9.620 +	}
   9.621 +
   9.622 +	void Close( bool bDeleteDevice )
   9.623 +	{
   9.624 +		// Make sure thread is attached to JVM/env
   9.625 +		JNIEnv *env;
   9.626 +		g_JVM->AttachCurrentThread( &env, NULL );
   9.627 +		pthread_setspecific( g_ThreadKey, (void*)env );
   9.628 +
   9.629 +		env->CallVoidMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerClose, m_nId );
   9.630 +
   9.631 +		hid_mutex_guard dataLock( &m_dataLock );
   9.632 +		m_vecData.clear();
   9.633 +
   9.634 +		// Clean and release pending feature report reads
   9.635 +		hid_mutex_guard cvLock( &m_cvLock );
   9.636 +		m_featureReport.clear();
   9.637 +		m_bIsWaitingForFeatureReport = false;
   9.638 +		m_nFeatureReportError = -ECONNRESET;
   9.639 +		pthread_cond_broadcast( &m_cv );
   9.640 +
   9.641 +		if ( bDeleteDevice )
   9.642 +		{
   9.643 +			delete m_pDevice;
   9.644 +			m_pDevice = nullptr;
   9.645 +		}
   9.646 +	}
   9.647 +
   9.648 +private:
   9.649 +	int m_nRefCount = 0;
   9.650 +	int m_nId = 0;
   9.651 +	hid_device_info *m_pInfo = nullptr;
   9.652 +	hid_device *m_pDevice = nullptr;
   9.653 +	bool m_bIsBLESteamController = false;
   9.654 +	int m_nDeviceRefCount = 0;
   9.655 +
   9.656 +	pthread_mutex_t m_dataLock = PTHREAD_MUTEX_INITIALIZER; // This lock has to be held to access m_vecData
   9.657 +	hid_buffer_pool m_vecData;
   9.658 +
   9.659 +	// For handling get_feature_report
   9.660 +	pthread_mutex_t m_cvLock = PTHREAD_MUTEX_INITIALIZER; // This lock has to be held to access any variables below
   9.661 +	pthread_cond_t m_cv = PTHREAD_COND_INITIALIZER;
   9.662 +	bool m_bIsWaitingForOpen = false;
   9.663 +	bool m_bOpenResult = false;
   9.664 +	bool m_bIsWaitingForFeatureReport = false;
   9.665 +	int m_nFeatureReportError = 0;
   9.666 +	hid_buffer m_featureReport;
   9.667 +
   9.668 +public:
   9.669 +	hid_device_ref<CHIDDevice> next;
   9.670 +};
   9.671 +
   9.672 +class CHIDDevice;
   9.673 +static pthread_mutex_t g_DevicesMutex = PTHREAD_MUTEX_INITIALIZER;
   9.674 +static hid_device_ref<CHIDDevice> g_Devices;
   9.675 +
   9.676 +static hid_device_ref<CHIDDevice> FindDevice( int nDeviceId )
   9.677 +{
   9.678 +	hid_device_ref<CHIDDevice> pDevice;
   9.679 +
   9.680 +	hid_mutex_guard l( &g_DevicesMutex );
   9.681 +	for ( pDevice = g_Devices; pDevice; pDevice = pDevice->next )
   9.682 +	{
   9.683 +		if ( pDevice->GetId() == nDeviceId )
   9.684 +		{
   9.685 +			break;
   9.686 +		}
   9.687 +	}
   9.688 +	return pDevice;
   9.689 +}
   9.690 +
   9.691 +static void ThreadDestroyed(void* value)
   9.692 +{
   9.693 +	/* The thread is being destroyed, detach it from the Java VM and set the g_ThreadKey value to NULL as required */
   9.694 +	JNIEnv *env = (JNIEnv*) value;
   9.695 +	if (env != NULL) {
   9.696 +		g_JVM->DetachCurrentThread();
   9.697 +		pthread_setspecific(g_ThreadKey, NULL);
   9.698 +	}
   9.699 +}
   9.700 +
   9.701 +extern "C"
   9.702 +JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceRegisterCallback)(JNIEnv *env, jobject thiz, jobject callbackHandler)
   9.703 +{
   9.704 +	LOGV( "HIDDeviceRegisterCallback()");
   9.705 +
   9.706 +	env->GetJavaVM( &g_JVM );
   9.707 +
   9.708 +	/*
   9.709 +	 * Create mThreadKey so we can keep track of the JNIEnv assigned to each thread
   9.710 +	 * Refer to http://developer.android.com/guide/practices/design/jni.html for the rationale behind this
   9.711 +	 */
   9.712 +	if (pthread_key_create(&g_ThreadKey, ThreadDestroyed) != 0) {
   9.713 +		__android_log_print(ANDROID_LOG_ERROR, TAG, "Error initializing pthread key");
   9.714 +	}
   9.715 +
   9.716 +	g_HIDDeviceManagerCallbackHandler = env->NewGlobalRef( callbackHandler );
   9.717 +	jclass objClass = env->GetObjectClass( callbackHandler );
   9.718 +	if ( objClass )
   9.719 +	{
   9.720 +		g_HIDDeviceManagerCallbackClass = reinterpret_cast< jclass >( env->NewGlobalRef(objClass) );
   9.721 +		g_midHIDDeviceManagerOpen = env->GetMethodID( g_HIDDeviceManagerCallbackClass, "openDevice", "(I)Z" );
   9.722 +		if ( !g_midHIDDeviceManagerOpen )
   9.723 +		{
   9.724 +			__android_log_print(ANDROID_LOG_ERROR, TAG, "HIDDeviceRegisterCallback: callback class missing openDevice" );
   9.725 +		}
   9.726 +		g_midHIDDeviceManagerSendOutputReport = env->GetMethodID( g_HIDDeviceManagerCallbackClass, "sendOutputReport", "(I[B)I" );
   9.727 +		if ( !g_midHIDDeviceManagerSendOutputReport )
   9.728 +		{
   9.729 +			__android_log_print(ANDROID_LOG_ERROR, TAG, "HIDDeviceRegisterCallback: callback class missing sendOutputReport" );
   9.730 +		}
   9.731 +		g_midHIDDeviceManagerSendFeatureReport = env->GetMethodID( g_HIDDeviceManagerCallbackClass, "sendFeatureReport", "(I[B)I" );
   9.732 +		if ( !g_midHIDDeviceManagerSendFeatureReport )
   9.733 +		{
   9.734 +			__android_log_print(ANDROID_LOG_ERROR, TAG, "HIDDeviceRegisterCallback: callback class missing sendFeatureReport" );
   9.735 +		}
   9.736 +		g_midHIDDeviceManagerGetFeatureReport = env->GetMethodID( g_HIDDeviceManagerCallbackClass, "getFeatureReport", "(I[B)Z" );
   9.737 +		if ( !g_midHIDDeviceManagerGetFeatureReport )
   9.738 +		{
   9.739 +			__android_log_print(ANDROID_LOG_ERROR, TAG, "HIDDeviceRegisterCallback: callback class missing getFeatureReport" );
   9.740 +		}
   9.741 +		g_midHIDDeviceManagerClose = env->GetMethodID( g_HIDDeviceManagerCallbackClass, "closeDevice", "(I)V" );
   9.742 +		if ( !g_midHIDDeviceManagerClose )
   9.743 +		{
   9.744 +			__android_log_print(ANDROID_LOG_ERROR, TAG, "HIDDeviceRegisterCallback: callback class missing closeDevice" );
   9.745 +		}
   9.746 +		env->DeleteLocalRef( objClass );
   9.747 +	}
   9.748 +}
   9.749 +
   9.750 +extern "C"
   9.751 +JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceReleaseCallback)(JNIEnv *env, jobject thiz)
   9.752 +{
   9.753 +	LOGV("HIDDeviceReleaseCallback");
   9.754 +	env->DeleteGlobalRef( g_HIDDeviceManagerCallbackClass );
   9.755 +	env->DeleteGlobalRef( g_HIDDeviceManagerCallbackHandler );
   9.756 +}
   9.757 +
   9.758 +extern "C"
   9.759 +JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface )
   9.760 +{
   9.761 +	LOGV( "HIDDeviceConnected() id=%d VID/PID = %.4x/%.4x, interface %d\n", nDeviceID, nVendorId, nProductId, nInterface );
   9.762 +
   9.763 +	hid_device_info *pInfo = new hid_device_info;
   9.764 +	memset( pInfo, 0, sizeof( *pInfo ) );
   9.765 +	pInfo->path = CreateStringFromJString( env, sIdentifier );
   9.766 +	pInfo->vendor_id = nVendorId;
   9.767 +	pInfo->product_id = nProductId;
   9.768 +	pInfo->serial_number = CreateWStringFromJString( env, sSerialNumber );
   9.769 +	pInfo->release_number = nReleaseNumber;
   9.770 +	pInfo->manufacturer_string = CreateWStringFromJString( env, sManufacturer );
   9.771 +	pInfo->product_string = CreateWStringFromJString( env, sProduct );
   9.772 +	pInfo->interface_number = nInterface;
   9.773 +
   9.774 +	hid_device_ref<CHIDDevice> pDevice( new CHIDDevice( nDeviceID, pInfo ) );
   9.775 +
   9.776 +	hid_mutex_guard l( &g_DevicesMutex );
   9.777 +	hid_device_ref<CHIDDevice> pLast, pCurr;
   9.778 +	for ( pCurr = g_Devices; pCurr; pLast = pCurr, pCurr = pCurr->next )
   9.779 +	{
   9.780 +		continue;
   9.781 +	}
   9.782 +	if ( pLast )
   9.783 +	{
   9.784 +		pLast->next = pDevice;
   9.785 +	}
   9.786 +	else
   9.787 +	{
   9.788 +		g_Devices = pDevice;
   9.789 +	}
   9.790 +}
   9.791 +
   9.792 +extern "C"
   9.793 +JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenPending)(JNIEnv *env, jobject thiz, int nDeviceID)
   9.794 +{
   9.795 +	LOGV( "HIDDeviceOpenPending() id=%d\n", nDeviceID );
   9.796 +	hid_device_ref<CHIDDevice> pDevice = FindDevice( nDeviceID );
   9.797 +	if ( pDevice )
   9.798 +	{
   9.799 +		pDevice->SetOpenPending();
   9.800 +	}
   9.801 +}
   9.802 +
   9.803 +extern "C"
   9.804 +JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenResult)(JNIEnv *env, jobject thiz, int nDeviceID, bool bOpened)
   9.805 +{
   9.806 +	LOGV( "HIDDeviceOpenResult() id=%d, result=%s\n", nDeviceID, bOpened ? "true" : "false" );
   9.807 +	hid_device_ref<CHIDDevice> pDevice = FindDevice( nDeviceID );
   9.808 +	if ( pDevice )
   9.809 +	{
   9.810 +		pDevice->SetOpenResult( bOpened );
   9.811 +	}
   9.812 +}
   9.813 +
   9.814 +extern "C"
   9.815 +JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceDisconnected)(JNIEnv *env, jobject thiz, int nDeviceID)
   9.816 +{
   9.817 +	LOGV( "HIDDeviceDisconnected() id=%d\n", nDeviceID );
   9.818 +	hid_device_ref<CHIDDevice> pDevice;
   9.819 +	{
   9.820 +		hid_mutex_guard l( &g_DevicesMutex );
   9.821 +		hid_device_ref<CHIDDevice> pLast, pCurr;
   9.822 +		for ( pCurr = g_Devices; pCurr; pLast = pCurr, pCurr = pCurr->next )
   9.823 +		{
   9.824 +			if ( pCurr->GetId() == nDeviceID )
   9.825 +			{
   9.826 +				pDevice = pCurr;
   9.827 +
   9.828 +				if ( pLast )
   9.829 +				{
   9.830 +					pLast->next = pCurr->next;
   9.831 +				}
   9.832 +				else
   9.833 +				{
   9.834 +					g_Devices = pCurr->next;
   9.835 +				}
   9.836 +			}
   9.837 +		}
   9.838 +	}
   9.839 +	if ( pDevice )
   9.840 +	{
   9.841 +		pDevice->Close( false );
   9.842 +	}
   9.843 +}
   9.844 +
   9.845 +extern "C"
   9.846 +JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceInputReport)(JNIEnv *env, jobject thiz, int nDeviceID, jbyteArray value)
   9.847 +{
   9.848 +	jbyte *pBuf = env->GetByteArrayElements(value, NULL);
   9.849 +	jsize nBufSize = env->GetArrayLength(value);
   9.850 +
   9.851 +//	LOGV( "HIDDeviceInput() id=%d len=%u\n", nDeviceID, nBufSize );
   9.852 +	hid_device_ref<CHIDDevice> pDevice = FindDevice( nDeviceID );
   9.853 +	if ( pDevice )
   9.854 +	{
   9.855 +		pDevice->ProcessInput( reinterpret_cast< const uint8_t* >( pBuf ), nBufSize );
   9.856 +	}
   9.857 +
   9.858 +	env->ReleaseByteArrayElements(value, pBuf, 0);
   9.859 +}
   9.860 +
   9.861 +extern "C"
   9.862 +JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceFeatureReport)(JNIEnv *env, jobject thiz, int nDeviceID, jbyteArray value)
   9.863 +{
   9.864 +	jbyte *pBuf = env->GetByteArrayElements(value, NULL);
   9.865 +	jsize nBufSize = env->GetArrayLength(value);
   9.866 +
   9.867 +	LOGV( "HIDDeviceFeatureReport() id=%d len=%u\n", nDeviceID, nBufSize );
   9.868 +	hid_device_ref<CHIDDevice> pDevice = FindDevice( nDeviceID );
   9.869 +	if ( pDevice )
   9.870 +	{
   9.871 +		pDevice->ProcessFeatureReport( reinterpret_cast< const uint8_t* >( pBuf ), nBufSize );
   9.872 +	}
   9.873 +
   9.874 +	env->ReleaseByteArrayElements(value, pBuf, 0);
   9.875 +}
   9.876 +
   9.877 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////
   9.878 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////
   9.879 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////
   9.880 +
   9.881 +extern "C"
   9.882 +{
   9.883 +
   9.884 +int hid_init(void)
   9.885 +{
   9.886 +	return 0;
   9.887 +}
   9.888 +
   9.889 +struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
   9.890 +{
   9.891 +	struct hid_device_info *root = NULL;
   9.892 +	hid_mutex_guard l( &g_DevicesMutex );
   9.893 +	for ( hid_device_ref<CHIDDevice> pDevice = g_Devices; pDevice; pDevice = pDevice->next )
   9.894 +	{
   9.895 +		const hid_device_info *info = pDevice->GetDeviceInfo();
   9.896 +		if ( ( vendor_id == 0 && product_id == 0 ) ||
   9.897 +			 ( vendor_id == info->vendor_id && product_id == info->product_id ) )
   9.898 +		{
   9.899 +			hid_device_info *dev = CopyHIDDeviceInfo( info );
   9.900 +			dev->next = root;
   9.901 +			root = dev;
   9.902 +		}
   9.903 +	}
   9.904 +	return root;
   9.905 +}
   9.906 +
   9.907 +void  HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
   9.908 +{
   9.909 +	while ( devs )
   9.910 +	{
   9.911 +		struct hid_device_info *next = devs->next;
   9.912 +		FreeHIDDeviceInfo( devs );
   9.913 +		devs = next;
   9.914 +	}
   9.915 +}
   9.916 +
   9.917 +HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
   9.918 +{
   9.919 +	// TODO: Implement
   9.920 +	return NULL;
   9.921 +}
   9.922 +
   9.923 +HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path, int bExclusive)
   9.924 +{
   9.925 +	LOGV( "hid_open_path( %s )", path );
   9.926 +
   9.927 +	hid_device_ref< CHIDDevice > pDevice;
   9.928 +	{
   9.929 +		hid_mutex_guard l( &g_DevicesMutex );
   9.930 +		for ( hid_device_ref<CHIDDevice> pCurr = g_Devices; pCurr; pCurr = pCurr->next )
   9.931 +		{
   9.932 +			if ( strcmp( pCurr->GetDeviceInfo()->path, path ) == 0 ) 
   9.933 +			{
   9.934 +				if ( pCurr->GetDevice() ) {
   9.935 +					pCurr->IncrementDeviceRefCount();
   9.936 +					return pCurr->GetDevice();
   9.937 +				}
   9.938 +
   9.939 +				// Hold a shared pointer to the controller for the duration
   9.940 +				pDevice = pCurr;
   9.941 +				break;
   9.942 +			}
   9.943 +		}
   9.944 +	}
   9.945 +	if ( pDevice && pDevice->BOpen() )
   9.946 +	{
   9.947 +		return pDevice->GetDevice();
   9.948 +	}
   9.949 +	return NULL;
   9.950 +}
   9.951 +
   9.952 +int  HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length)
   9.953 +{
   9.954 +	LOGV( "hid_write id=%d length=%u", device->nId, length );
   9.955 +	hid_device_ref<CHIDDevice> pDevice = FindDevice( device->nId );
   9.956 +	if ( pDevice )
   9.957 +	{
   9.958 +		return pDevice->SendOutputReport( data, length );
   9.959 +	}
   9.960 +	return -1; // Controller was disconnected
   9.961 +}
   9.962 +
   9.963 +// TODO: Implement timeout?
   9.964 +int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds)
   9.965 +{
   9.966 +//	LOGV( "hid_read_timeout id=%d length=%u timeout=%d", device->nId, length, milliseconds );
   9.967 +	hid_device_ref<CHIDDevice> pDevice = FindDevice( device->nId );
   9.968 +	if ( pDevice )
   9.969 +	{
   9.970 +		return pDevice->GetInput( data, length );
   9.971 +	}
   9.972 +	LOGV( "controller was disconnected" );
   9.973 +	return -1; // Controller was disconnected
   9.974 +}
   9.975 +
   9.976 +// TODO: Implement blocking
   9.977 +int  HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length)
   9.978 +{
   9.979 +	LOGV( "hid_read id=%d length=%u", device->nId, length );
   9.980 +	return hid_read_timeout( device, data, length, 0 );
   9.981 +}
   9.982 +
   9.983 +// TODO: Implement?
   9.984 +int  HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock)
   9.985 +{
   9.986 +	return -1;
   9.987 +}
   9.988 +
   9.989 +int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length)
   9.990 +{
   9.991 +	LOGV( "hid_send_feature_report id=%d length=%u", device->nId, length );
   9.992 +	hid_device_ref<CHIDDevice> pDevice = FindDevice( device->nId );
   9.993 +	if ( pDevice )
   9.994 +	{
   9.995 +		return pDevice->SendFeatureReport( data, length );
   9.996 +	}
   9.997 +	return -1; // Controller was disconnected
   9.998 +}
   9.999 +
  9.1000 +
  9.1001 +// Synchronous operation. Will block until completed.
  9.1002 +int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length)
  9.1003 +{
  9.1004 +	LOGV( "hid_get_feature_report id=%d length=%u", device->nId, length );
  9.1005 +	hid_device_ref<CHIDDevice> pDevice = FindDevice( device->nId );
  9.1006 +	if ( pDevice )
  9.1007 +	{
  9.1008 +		return pDevice->GetFeatureReport( data, length );
  9.1009 +	}
  9.1010 +	return -1; // Controller was disconnected
  9.1011 +}
  9.1012 +
  9.1013 +
  9.1014 +void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device)
  9.1015 +{
  9.1016 +	LOGV( "hid_close id=%d", device->nId );
  9.1017 +	hid_device_ref<CHIDDevice> pDevice = FindDevice( device->nId );
  9.1018 +	if ( pDevice )
  9.1019 +	{
  9.1020 +		pDevice->DecrementDeviceRefCount();
  9.1021 +		if ( pDevice->GetDeviceRefCount() == 0 ) {
  9.1022 +			pDevice->Close( true );
  9.1023 +		}
  9.1024 +	}
  9.1025 +	else
  9.1026 +	{
  9.1027 +		// Couldn't find it, it's already closed
  9.1028 +		delete device;
  9.1029 +	}
  9.1030 +
  9.1031 +}
  9.1032 +
  9.1033 +int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen)
  9.1034 +{
  9.1035 +	hid_device_ref<CHIDDevice> pDevice = FindDevice( device->nId );
  9.1036 +	if ( pDevice )
  9.1037 +	{
  9.1038 +		wcsncpy( string, pDevice->GetDeviceInfo()->manufacturer_string, maxlen );
  9.1039 +		return 0;
  9.1040 +	}
  9.1041 +	return -1;
  9.1042 +}
  9.1043 +
  9.1044 +int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen)
  9.1045 +{
  9.1046 +	hid_device_ref<CHIDDevice> pDevice = FindDevice( device->nId );
  9.1047 +	if ( pDevice )
  9.1048 +	{
  9.1049 +		wcsncpy( string, pDevice->GetDeviceInfo()->product_string, maxlen );
  9.1050 +		return 0;
  9.1051 +	}
  9.1052 +	return -1;
  9.1053 +}
  9.1054 +
  9.1055 +int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen)
  9.1056 +{
  9.1057 +	hid_device_ref<CHIDDevice> pDevice = FindDevice( device->nId );
  9.1058 +	if ( pDevice )
  9.1059 +	{
  9.1060 +		wcsncpy( string, pDevice->GetDeviceInfo()->serial_number, maxlen );
  9.1061 +		return 0;
  9.1062 +	}
  9.1063 +	return -1;
  9.1064 +}
  9.1065 +
  9.1066 +int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen)
  9.1067 +{
  9.1068 +	return -1;
  9.1069 +}
  9.1070 +
  9.1071 +HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device)
  9.1072 +{
  9.1073 +	return NULL;
  9.1074 +}
  9.1075 +
  9.1076 +int hid_exit(void)
  9.1077 +{
  9.1078 +	return 0;
  9.1079 +}
  9.1080 +
  9.1081 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/hidapi/android/jni/Android.mk	Thu Aug 09 16:05:48 2018 -0700
    10.3 @@ -0,0 +1,16 @@
    10.4 +LOCAL_PATH:= $(call my-dir)
    10.5 +
    10.6 +HIDAPI_ROOT_REL:= ../..
    10.7 +HIDAPI_ROOT_ABS:= $(LOCAL_PATH)/../..
    10.8 +
    10.9 +include $(CLEAR_VARS)
   10.10 +
   10.11 +LOCAL_CPPFLAGS += -std=c++11
   10.12 +
   10.13 +LOCAL_SRC_FILES := \
   10.14 +  $(HIDAPI_ROOT_REL)/android/hid.cpp
   10.15 +
   10.16 +LOCAL_MODULE := libhidapi
   10.17 +LOCAL_LDLIBS := -llog
   10.18 +
   10.19 +include $(BUILD_SHARED_LIBRARY)
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/hidapi/android/jni/Application.mk	Thu Aug 09 16:05:48 2018 -0700
    11.3 @@ -0,0 +1,2 @@
    11.4 +APP_STL := gnustl_static
    11.5 +APP_ABI := armeabi-v7a
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/hidapi/android/project.properties	Thu Aug 09 16:05:48 2018 -0700
    12.3 @@ -0,0 +1,14 @@
    12.4 +# This file is automatically generated by Android Tools.
    12.5 +# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
    12.6 +#
    12.7 +# This file must be checked in Version Control Systems.
    12.8 +#
    12.9 +# To customize properties used by the Ant build system edit
   12.10 +# "ant.properties", and override values to adapt the script to your
   12.11 +# project structure.
   12.12 +#
   12.13 +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
   12.14 +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
   12.15 +
   12.16 +# Project target.
   12.17 +target=android-21
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/src/hidapi/bootstrap	Thu Aug 09 16:05:48 2018 -0700
    13.3 @@ -0,0 +1,2 @@
    13.4 +#!/bin/sh -x
    13.5 +autoreconf --install --verbose --force
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/src/hidapi/configure.ac	Thu Aug 09 16:05:48 2018 -0700
    14.3 @@ -0,0 +1,236 @@
    14.4 +AC_PREREQ(2.63)
    14.5 +
    14.6 +# Version number. This is currently the only place.
    14.7 +m4_define([HIDAPI_MAJOR],   0)
    14.8 +m4_define([HIDAPI_MINOR],   8)
    14.9 +m4_define([HIDAPI_RELEASE], 0)
   14.10 +m4_define([HIDAPI_RC],      -rc1)
   14.11 +m4_define([VERSION_STRING], HIDAPI_MAJOR[.]HIDAPI_MINOR[.]HIDAPI_RELEASE[]HIDAPI_RC)
   14.12 +
   14.13 +AC_INIT([hidapi],[VERSION_STRING],[alan@signal11.us])
   14.14 +
   14.15 +# Library soname version
   14.16 +# Follow the following rules (particularly the ones in the second link):
   14.17 +#  http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
   14.18 +#  http://sourceware.org/autobook/autobook/autobook_91.html
   14.19 +lt_current="0"
   14.20 +lt_revision="0"
   14.21 +lt_age="0"
   14.22 +LTLDFLAGS="-version-info ${lt_current}:${lt_revision}:${lt_age}"
   14.23 +
   14.24 +AC_CONFIG_MACRO_DIR([m4])
   14.25 +AM_INIT_AUTOMAKE([foreign -Wall -Werror])
   14.26 +AC_CONFIG_MACRO_DIR([m4])
   14.27 +
   14.28 +m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
   14.29 +LT_INIT
   14.30 +
   14.31 +AC_PROG_CC
   14.32 +AC_PROG_CXX
   14.33 +AC_PROG_OBJC
   14.34 +PKG_PROG_PKG_CONFIG
   14.35 +
   14.36 +
   14.37 +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
   14.38 +
   14.39 +hidapi_lib_error() {
   14.40 +	echo ""
   14.41 +	echo "  Library $1 was not found on this system."
   14.42 +	echo "  Please install it and re-run ./configure"
   14.43 +	echo ""
   14.44 +	exit 1
   14.45 +}
   14.46 +
   14.47 +hidapi_prog_error() {
   14.48 +	echo ""
   14.49 +	echo "  Program $1 was not found on this system."
   14.50 +	echo "  This program is part of $2."
   14.51 +	echo "  Please install it and re-run ./configure"
   14.52 +	echo ""
   14.53 +	exit 1
   14.54 +}
   14.55 +
   14.56 +AC_MSG_CHECKING([operating system])
   14.57 +AC_MSG_RESULT($host)
   14.58 +case $host in
   14.59 +*-linux*)
   14.60 +	AC_MSG_RESULT([ (Linux back-end)])
   14.61 +	AC_DEFINE(OS_LINUX, 1, [Linux implementations])
   14.62 +	AC_SUBST(OS_LINUX)
   14.63 +	backend="linux"
   14.64 +	os="linux"
   14.65 +	threads="pthreads"
   14.66 +
   14.67 +	# HIDAPI/hidraw libs
   14.68 +	PKG_CHECK_MODULES([libudev], [libudev], true, [hidapi_lib_error libudev])
   14.69 +	LIBS_HIDRAW_PR+=" $libudev_LIBS"
   14.70 +	CFLAGS_HIDRAW+=" $libudev_CFLAGS"
   14.71 +
   14.72 +	# HIDAPI/libusb libs
   14.73 +	AC_CHECK_LIB([rt], [clock_gettime], [LIBS_LIBUSB_PRIVATE+=" -lrt"], [hidapi_lib_error librt])
   14.74 +	PKG_CHECK_MODULES([libusb], [libusb-1.0 >= 1.0.9], true, [hidapi_lib_error libusb-1.0])
   14.75 +	LIBS_LIBUSB_PRIVATE+=" $libusb_LIBS"
   14.76 +	CFLAGS_LIBUSB+=" $libusb_CFLAGS"
   14.77 +	;;
   14.78 +*-darwin*)
   14.79 +	AC_MSG_RESULT([ (Mac OS X back-end)])
   14.80 +	AC_DEFINE(OS_DARWIN, 1, [Mac implementation])
   14.81 +	AC_SUBST(OS_DARWIN)
   14.82 +	backend="mac"
   14.83 +	os="darwin"
   14.84 +	threads="pthreads"
   14.85 +	LIBS="${LIBS} -framework IOKit -framework CoreFoundation"
   14.86 +	;;
   14.87 +*-freebsd*)
   14.88 +	AC_MSG_RESULT([ (FreeBSD back-end)])
   14.89 +	AC_DEFINE(OS_FREEBSD, 1, [FreeBSD implementation])
   14.90 +	AC_SUBST(OS_FREEBSD)
   14.91 +	backend="libusb"
   14.92 +	os="freebsd"
   14.93 +	threads="pthreads"
   14.94 +
   14.95 +	CFLAGS="$CFLAGS -I/usr/local/include"
   14.96 +	LDFLAGS="$LDFLAGS -L/usr/local/lib"
   14.97 +	LIBS="${LIBS}"
   14.98 +	AC_CHECK_LIB([usb], [libusb_init], [LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} -lusb"], [hidapi_lib_error libusb])
   14.99 +	AC_CHECK_LIB([iconv], [iconv_open], [LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} -liconv"], [hidapi_lib_error libiconv])
  14.100 +	echo libs_priv: $LIBS_LIBUSB_PRIVATE
  14.101 +	;;
  14.102 +*-kfreebsd*)
  14.103 +	AC_MSG_RESULT([ (kFreeBSD back-end)])
  14.104 +	AC_DEFINE(OS_KFREEBSD, 1, [kFreeBSD implementation])
  14.105 +	AC_SUBST(OS_KFREEBSD)
  14.106 +	backend="libusb"
  14.107 +	os="kfreebsd"
  14.108 +	threads="pthreads"
  14.109 +
  14.110 +	AC_CHECK_LIB([usb], [libusb_init], [LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} -lusb"], [hidapi_lib_error libusb])
  14.111 +	echo libs_priv: $LIBS_LIBUSB_PRIVATE
  14.112 +	;;
  14.113 +*-mingw*)
  14.114 +	AC_MSG_RESULT([ (Windows back-end, using MinGW)])
  14.115 +	backend="windows"
  14.116 +	os="windows"
  14.117 +	threads="windows"
  14.118 +	win_implementation="mingw"
  14.119 +	;;
  14.120 +*-cygwin*)
  14.121 +	AC_MSG_RESULT([ (Windows back-end, using Cygwin)])
  14.122 +	backend="windows"
  14.123 +	os="windows"
  14.124 +	threads="windows"
  14.125 +	win_implementation="cygwin"
  14.126 +	;;
  14.127 +*)
  14.128 +	AC_MSG_ERROR([HIDAPI is not supported on your operating system yet])
  14.129 +esac
  14.130 +
  14.131 +LIBS_HIDRAW="${LIBS} ${LIBS_HIDRAW_PR}"
  14.132 +LIBS_LIBUSB="${LIBS} ${LIBS_LIBUSB_PRIVATE}"
  14.133 +AC_SUBST([LIBS_HIDRAW])
  14.134 +AC_SUBST([LIBS_LIBUSB])
  14.135 +AC_SUBST([CFLAGS_LIBUSB])
  14.136 +AC_SUBST([CFLAGS_HIDRAW])
  14.137 +
  14.138 +if test "x$os" = xwindows; then
  14.139 +	AC_DEFINE(OS_WINDOWS, 1, [Windows implementations])
  14.140 +	AC_SUBST(OS_WINDOWS)
  14.141 +	LDFLAGS="${LDFLAGS} -no-undefined"
  14.142 +	LIBS="${LIBS} -lsetupapi"
  14.143 +fi
  14.144 +
  14.145 +if test "x$threads" = xpthreads; then
  14.146 +	AX_PTHREAD([found_pthreads=yes], [found_pthreads=no])
  14.147 +
  14.148 +	if test "x$found_pthreads" = xyes; then
  14.149 +		if test "x$os" = xlinux; then
  14.150 +			# Only use pthreads for libusb implementation on Linux.
  14.151 +			LIBS_LIBUSB="$PTHREAD_LIBS $LIBS_LIBUSB"
  14.152 +			CFLAGS_LIBUSB="$CFLAGS_LIBUSB $PTHREAD_CFLAGS"
  14.153 +			# There's no separate CC on Linux for threading,
  14.154 +			# so it's ok that both implementations use $PTHREAD_CC
  14.155 +			CC="$PTHREAD_CC"
  14.156 +		else
  14.157 +			LIBS="$PTHREAD_LIBS $LIBS"
  14.158 +			CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
  14.159 +			CC="$PTHREAD_CC"
  14.160 +		fi
  14.161 +	fi
  14.162 +fi
  14.163 +
  14.164 +# Test GUI
  14.165 +AC_ARG_ENABLE([testgui],
  14.166 +	[AS_HELP_STRING([--enable-testgui],
  14.167 +		[enable building of test GUI (default n)])],
  14.168 +	[testgui_enabled=$enableval],
  14.169 +	[testgui_enabled='no'])
  14.170 +AM_CONDITIONAL([BUILD_TESTGUI], [test "x$testgui_enabled" != "xno"])
  14.171 +
  14.172 +# Configure the MacOS TestGUI app bundle
  14.173 +rm -Rf testgui/TestGUI.app
  14.174 +mkdir -p testgui/TestGUI.app
  14.175 +cp -R ${srcdir}/testgui/TestGUI.app.in/* testgui/TestGUI.app
  14.176 +chmod -R u+w testgui/TestGUI.app
  14.177 +mkdir testgui/TestGUI.app/Contents/MacOS/
  14.178 +
  14.179 +if test "x$testgui_enabled" != "xno"; then
  14.180 +	if test "x$os" = xdarwin; then
  14.181 +		# On Mac OS, don't use pkg-config.
  14.182 +		AC_CHECK_PROG([foxconfig], [fox-config], [fox-config], false)
  14.183 +		if test "x$foxconfig" = "xfalse"; then
  14.184 +			hidapi_prog_error fox-config "FOX Toolkit"
  14.185 +		fi
  14.186 +		LIBS_TESTGUI+=`$foxconfig --libs`
  14.187 +		LIBS_TESTGUI+=" -framework Cocoa -L/usr/X11R6/lib"
  14.188 +		CFLAGS_TESTGUI+=`$foxconfig --cflags`
  14.189 +		OBJCFLAGS+=" -x objective-c++"
  14.190 +	elif test "x$os" = xwindows; then
  14.191 +		# On Windows, just set the paths for Fox toolkit
  14.192 +		if test "x$win_implementation" = xmingw; then
  14.193 +			CFLAGS_TESTGUI="-I\$(srcdir)/../../hidapi-externals/fox/include -g -c"
  14.194 +			LIBS_TESTGUI=" -mwindows \$(srcdir)/../../hidapi-externals/fox/lib/libFOX-1.6.a -lgdi32 -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lkernel32"
  14.195 +		else
  14.196 +			# Cygwin
  14.197 +			CFLAGS_TESTGUI="-DWIN32 -I\$(srcdir)/../../hidapi-externals/fox/include -g -c"
  14.198 +			LIBS_TESTGUI="\$(srcdir)/../../hidapi-externals/fox/lib/libFOX-cygwin-1.6.a -lgdi32 -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lkernel32"
  14.199 +		fi
  14.200 +	else
  14.201 +		# On Linux and FreeBSD platforms, use pkg-config to find fox.
  14.202 +		PKG_CHECK_MODULES([fox], [fox17], [], [PKG_CHECK_MODULES([fox], [fox])])
  14.203 +		LIBS_TESTGUI="${LIBS_TESTGUI} $fox_LIBS"
  14.204 +		if test "x$os" = xfreebsd; then
  14.205 +			LIBS_TESTGUI="${LIBS_TESTGUI} -L/usr/local/lib"
  14.206 +		fi
  14.207 +		CFLAGS_TESTGUI="${CFLAGS_TESTGUI} $fox_CFLAGS"
  14.208 +	fi
  14.209 +fi
  14.210 +AC_SUBST([LIBS_TESTGUI])
  14.211 +AC_SUBST([CFLAGS_TESTGUI])
  14.212 +AC_SUBST([backend])
  14.213 +
  14.214 +# OS info for Automake
  14.215 +AM_CONDITIONAL(OS_LINUX, test "x$os" = xlinux)
  14.216 +AM_CONDITIONAL(OS_DARWIN, test "x$os" = xdarwin)
  14.217 +AM_CONDITIONAL(OS_FREEBSD, test "x$os" = xfreebsd)
  14.218 +AM_CONDITIONAL(OS_KFREEBSD, test "x$os" = xkfreebsd)
  14.219 +AM_CONDITIONAL(OS_WINDOWS, test "x$os" = xwindows)
  14.220 +
  14.221 +AC_CONFIG_HEADERS([config.h])
  14.222 +
  14.223 +if test "x$os" = "xlinux"; then
  14.224 +	AC_CONFIG_FILES([pc/hidapi-hidraw.pc])
  14.225 +	AC_CONFIG_FILES([pc/hidapi-libusb.pc])
  14.226 +else
  14.227 +	AC_CONFIG_FILES([pc/hidapi.pc])
  14.228 +fi
  14.229 +
  14.230 +AC_SUBST(LTLDFLAGS)
  14.231 +
  14.232 +AC_CONFIG_FILES([Makefile \
  14.233 +	hidtest/Makefile \
  14.234 +	libusb/Makefile \
  14.235 +	linux/Makefile \
  14.236 +	mac/Makefile \
  14.237 +	testgui/Makefile \
  14.238 +	windows/Makefile])
  14.239 +AC_OUTPUT
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/src/hidapi/doxygen/Doxyfile	Thu Aug 09 16:05:48 2018 -0700
    15.3 @@ -0,0 +1,1630 @@
    15.4 +# Doxyfile 1.7.1
    15.5 +
    15.6 +# This file describes the settings to be used by the documentation system
    15.7 +# doxygen (www.doxygen.org) for a project
    15.8 +#
    15.9 +# All text after a hash (#) is considered a comment and will be ignored
   15.10 +# The format is:
   15.11 +#       TAG = value [value, ...]
   15.12 +# For lists items can also be appended using:
   15.13 +#       TAG += value [value, ...]
   15.14 +# Values that contain spaces should be placed between quotes (" ")
   15.15 +
   15.16 +#---------------------------------------------------------------------------
   15.17 +# Project related configuration options
   15.18 +#---------------------------------------------------------------------------
   15.19 +
   15.20 +# This tag specifies the encoding used for all characters in the config file
   15.21 +# that follow. The default is UTF-8 which is also the encoding used for all
   15.22 +# text before the first occurrence of this tag. Doxygen uses libiconv (or the
   15.23 +# iconv built into libc) for the transcoding. See
   15.24 +# http://www.gnu.org/software/libiconv for the list of possible encodings.
   15.25 +
   15.26 +DOXYFILE_ENCODING      = UTF-8
   15.27 +
   15.28 +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
   15.29 +# by quotes) that should identify the project.
   15.30 +
   15.31 +PROJECT_NAME           = hidapi
   15.32 +
   15.33 +# The PROJECT_NUMBER tag can be used to enter a project or revision number.
   15.34 +# This could be handy for archiving the generated documentation or
   15.35 +# if some version control system is used.
   15.36 +
   15.37 +PROJECT_NUMBER         =
   15.38 +
   15.39 +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
   15.40 +# base path where the generated documentation will be put.
   15.41 +# If a relative path is entered, it will be relative to the location
   15.42 +# where doxygen was started. If left blank the current directory will be used.
   15.43 +
   15.44 +OUTPUT_DIRECTORY       =
   15.45 +
   15.46 +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
   15.47 +# 4096 sub-directories (in 2 levels) under the output directory of each output
   15.48 +# format and will distribute the generated files over these directories.
   15.49 +# Enabling this option can be useful when feeding doxygen a huge amount of
   15.50 +# source files, where putting all generated files in the same directory would
   15.51 +# otherwise cause performance problems for the file system.
   15.52 +
   15.53 +CREATE_SUBDIRS         = NO
   15.54 +
   15.55 +# The OUTPUT_LANGUAGE tag is used to specify the language in which all
   15.56 +# documentation generated by doxygen is written. Doxygen will use this
   15.57 +# information to generate all constant output in the proper language.
   15.58 +# The default language is English, other supported languages are:
   15.59 +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
   15.60 +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
   15.61 +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
   15.62 +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
   15.63 +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
   15.64 +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
   15.65 +
   15.66 +OUTPUT_LANGUAGE        = English
   15.67 +
   15.68 +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
   15.69 +# include brief member descriptions after the members that are listed in
   15.70 +# the file and class documentation (similar to JavaDoc).
   15.71 +# Set to NO to disable this.
   15.72 +
   15.73 +BRIEF_MEMBER_DESC      = YES
   15.74 +
   15.75 +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
   15.76 +# the brief description of a member or function before the detailed description.
   15.77 +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
   15.78 +# brief descriptions will be completely suppressed.
   15.79 +
   15.80 +REPEAT_BRIEF           = YES
   15.81 +
   15.82 +# This tag implements a quasi-intelligent brief description abbreviator
   15.83 +# that is used to form the text in various listings. Each string
   15.84 +# in this list, if found as the leading text of the brief description, will be
   15.85 +# stripped from the text and the result after processing the whole list, is
   15.86 +# used as the annotated text. Otherwise, the brief description is used as-is.
   15.87 +# If left blank, the following values are used ("$name" is automatically
   15.88 +# replaced with the name of the entity): "The $name class" "The $name widget"
   15.89 +# "The $name file" "is" "provides" "specifies" "contains"
   15.90 +# "represents" "a" "an" "the"
   15.91 +
   15.92 +ABBREVIATE_BRIEF       =
   15.93 +
   15.94 +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
   15.95 +# Doxygen will generate a detailed section even if there is only a brief
   15.96 +# description.
   15.97 +
   15.98 +ALWAYS_DETAILED_SEC    = NO
   15.99 +
  15.100 +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
  15.101 +# inherited members of a class in the documentation of that class as if those
  15.102 +# members were ordinary class members. Constructors, destructors and assignment
  15.103 +# operators of the base classes will not be shown.
  15.104 +
  15.105 +INLINE_INHERITED_MEMB  = NO
  15.106 +
  15.107 +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
  15.108 +# path before files name in the file list and in the header files. If set
  15.109 +# to NO the shortest path that makes the file name unique will be used.
  15.110 +
  15.111 +FULL_PATH_NAMES        = YES
  15.112 +
  15.113 +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
  15.114 +# can be used to strip a user-defined part of the path. Stripping is
  15.115 +# only done if one of the specified strings matches the left-hand part of
  15.116 +# the path. The tag can be used to show relative paths in the file list.
  15.117 +# If left blank the directory from which doxygen is run is used as the
  15.118 +# path to strip.
  15.119 +
  15.120 +STRIP_FROM_PATH        =
  15.121 +
  15.122 +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
  15.123 +# the path mentioned in the documentation of a class, which tells
  15.124 +# the reader which header file to include in order to use a class.
  15.125 +# If left blank only the name of the header file containing the class
  15.126 +# definition is used. Otherwise one should specify the include paths that
  15.127 +# are normally passed to the compiler using the -I flag.
  15.128 +
  15.129 +STRIP_FROM_INC_PATH    =
  15.130 +
  15.131 +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
  15.132 +# (but less readable) file names. This can be useful is your file systems
  15.133 +# doesn't support long names like on DOS, Mac, or CD-ROM.
  15.134 +
  15.135 +SHORT_NAMES            = NO
  15.136 +
  15.137 +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
  15.138 +# will interpret the first line (until the first dot) of a JavaDoc-style
  15.139 +# comment as the brief description. If set to NO, the JavaDoc
  15.140 +# comments will behave just like regular Qt-style comments
  15.141 +# (thus requiring an explicit @brief command for a brief description.)
  15.142 +
  15.143 +JAVADOC_AUTOBRIEF      = NO
  15.144 +
  15.145 +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
  15.146 +# interpret the first line (until the first dot) of a Qt-style
  15.147 +# comment as the brief description. If set to NO, the comments
  15.148 +# will behave just like regular Qt-style comments (thus requiring
  15.149 +# an explicit \brief command for a brief description.)
  15.150 +
  15.151 +QT_AUTOBRIEF           = NO
  15.152 +
  15.153 +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
  15.154 +# treat a multi-line C++ special comment block (i.e. a block of //! or ///
  15.155 +# comments) as a brief description. This used to be the default behaviour.
  15.156 +# The new default is to treat a multi-line C++ comment block as a detailed
  15.157 +# description. Set this tag to YES if you prefer the old behaviour instead.
  15.158 +
  15.159 +MULTILINE_CPP_IS_BRIEF = NO
  15.160 +
  15.161 +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
  15.162 +# member inherits the documentation from any documented member that it
  15.163 +# re-implements.
  15.164 +
  15.165 +INHERIT_DOCS           = YES
  15.166 +
  15.167 +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
  15.168 +# a new page for each member. If set to NO, the documentation of a member will
  15.169 +# be part of the file/class/namespace that contains it.
  15.170 +
  15.171 +SEPARATE_MEMBER_PAGES  = NO
  15.172 +
  15.173 +# The TAB_SIZE tag can be used to set the number of spaces in a tab.
  15.174 +# Doxygen uses this value to replace tabs by spaces in code fragments.
  15.175 +
  15.176 +TAB_SIZE               = 8
  15.177 +
  15.178 +# This tag can be used to specify a number of aliases that acts
  15.179 +# as commands in the documentation. An alias has the form "name=value".
  15.180 +# For example adding "sideeffect=\par Side Effects:\n" will allow you to
  15.181 +# put the command \sideeffect (or @sideeffect) in the documentation, which
  15.182 +# will result in a user-defined paragraph with heading "Side Effects:".
  15.183 +# You can put \n's in the value part of an alias to insert newlines.
  15.184 +
  15.185 +ALIASES                =
  15.186 +
  15.187 +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
  15.188 +# sources only. Doxygen will then generate output that is more tailored for C.
  15.189 +# For instance, some of the names that are used will be different. The list
  15.190 +# of all members will be omitted, etc.
  15.191 +
  15.192 +OPTIMIZE_OUTPUT_FOR_C  = YES
  15.193 +
  15.194 +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
  15.195 +# sources only. Doxygen will then generate output that is more tailored for
  15.196 +# Java. For instance, namespaces will be presented as packages, qualified
  15.197 +# scopes will look different, etc.
  15.198 +
  15.199 +OPTIMIZE_OUTPUT_JAVA   = NO
  15.200 +
  15.201 +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
  15.202 +# sources only. Doxygen will then generate output that is more tailored for
  15.203 +# Fortran.
  15.204 +
  15.205 +OPTIMIZE_FOR_FORTRAN   = NO
  15.206 +
  15.207 +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
  15.208 +# sources. Doxygen will then generate output that is tailored for
  15.209 +# VHDL.
  15.210 +
  15.211 +OPTIMIZE_OUTPUT_VHDL   = NO
  15.212 +
  15.213 +# Doxygen selects the parser to use depending on the extension of the files it
  15.214 +# parses. With this tag you can assign which parser to use for a given extension.
  15.215 +# Doxygen has a built-in mapping, but you can override or extend it using this
  15.216 +# tag. The format is ext=language, where ext is a file extension, and language
  15.217 +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
  15.218 +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
  15.219 +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
  15.220 +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
  15.221 +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
  15.222 +
  15.223 +EXTENSION_MAPPING      =
  15.224 +
  15.225 +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
  15.226 +# to include (a tag file for) the STL sources as input, then you should
  15.227 +# set this tag to YES in order to let doxygen match functions declarations and
  15.228 +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
  15.229 +# func(std::string) {}). This also make the inheritance and collaboration
  15.230 +# diagrams that involve STL classes more complete and accurate.
  15.231 +
  15.232 +BUILTIN_STL_SUPPORT    = NO
  15.233 +
  15.234 +# If you use Microsoft's C++/CLI language, you should set this option to YES to
  15.235 +# enable parsing support.
  15.236 +
  15.237 +CPP_CLI_SUPPORT        = NO
  15.238 +
  15.239 +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
  15.240 +# Doxygen will parse them like normal C++ but will assume all classes use public
  15.241 +# instead of private inheritance when no explicit protection keyword is present.
  15.242 +
  15.243 +SIP_SUPPORT            = NO
  15.244 +
  15.245 +# For Microsoft's IDL there are propget and propput attributes to indicate getter
  15.246 +# and setter methods for a property. Setting this option to YES (the default)
  15.247 +# will make doxygen to replace the get and set methods by a property in the
  15.248 +# documentation. This will only work if the methods are indeed getting or
  15.249 +# setting a simple type. If this is not the case, or you want to show the
  15.250 +# methods anyway, you should set this option to NO.
  15.251 +
  15.252 +IDL_PROPERTY_SUPPORT   = YES
  15.253 +
  15.254 +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
  15.255 +# tag is set to YES, then doxygen will reuse the documentation of the first
  15.256 +# member in the group (if any) for the other members of the group. By default
  15.257 +# all members of a group must be documented explicitly.
  15.258 +
  15.259 +DISTRIBUTE_GROUP_DOC   = NO
  15.260 +
  15.261 +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
  15.262 +# the same type (for instance a group of public functions) to be put as a
  15.263 +# subgroup of that type (e.g. under the Public Functions section). Set it to
  15.264 +# NO to prevent subgrouping. Alternatively, this can be done per class using
  15.265 +# the \nosubgrouping command.
  15.266 +
  15.267 +SUBGROUPING            = YES
  15.268 +
  15.269 +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
  15.270 +# is documented as struct, union, or enum with the name of the typedef. So
  15.271 +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
  15.272 +# with name TypeT. When disabled the typedef will appear as a member of a file,
  15.273 +# namespace, or class. And the struct will be named TypeS. This can typically
  15.274 +# be useful for C code in case the coding convention dictates that all compound
  15.275 +# types are typedef'ed and only the typedef is referenced, never the tag name.
  15.276 +
  15.277 +TYPEDEF_HIDES_STRUCT   = NO
  15.278 +
  15.279 +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
  15.280 +# determine which symbols to keep in memory and which to flush to disk.
  15.281 +# When the cache is full, less often used symbols will be written to disk.
  15.282 +# For small to medium size projects (<1000 input files) the default value is
  15.283 +# probably good enough. For larger projects a too small cache size can cause
  15.284 +# doxygen to be busy swapping symbols to and from disk most of the time
  15.285 +# causing a significant performance penality.
  15.286 +# If the system has enough physical memory increasing the cache will improve the
  15.287 +# performance by keeping more symbols in memory. Note that the value works on
  15.288 +# a logarithmic scale so increasing the size by one will rougly double the
  15.289 +# memory usage. The cache size is given by this formula:
  15.290 +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
  15.291 +# corresponding to a cache size of 2^16 = 65536 symbols
  15.292 +
  15.293 +SYMBOL_CACHE_SIZE      = 0
  15.294 +
  15.295 +#---------------------------------------------------------------------------
  15.296 +# Build related configuration options
  15.297 +#---------------------------------------------------------------------------
  15.298 +
  15.299 +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
  15.300 +# documentation are documented, even if no documentation was available.
  15.301 +# Private class members and static file members will be hidden unless
  15.302 +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
  15.303 +
  15.304 +EXTRACT_ALL            = NO
  15.305 +
  15.306 +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
  15.307 +# will be included in the documentation.
  15.308 +
  15.309 +EXTRACT_PRIVATE        = NO
  15.310 +
  15.311 +# If the EXTRACT_STATIC tag is set to YES all static members of a file
  15.312 +# will be included in the documentation.
  15.313 +
  15.314 +EXTRACT_STATIC         = NO
  15.315 +
  15.316 +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
  15.317 +# defined locally in source files will be included in the documentation.
  15.318 +# If set to NO only classes defined in header files are included.
  15.319 +
  15.320 +EXTRACT_LOCAL_CLASSES  = YES
  15.321 +
  15.322 +# This flag is only useful for Objective-C code. When set to YES local
  15.323 +# methods, which are defined in the implementation section but not in
  15.324 +# the interface are included in the documentation.
  15.325 +# If set to NO (the default) only methods in the interface are included.
  15.326 +
  15.327 +EXTRACT_LOCAL_METHODS  = NO
  15.328 +
  15.329 +# If this flag is set to YES, the members of anonymous namespaces will be
  15.330 +# extracted and appear in the documentation as a namespace called
  15.331 +# 'anonymous_namespace{file}', where file will be replaced with the base
  15.332 +# name of the file that contains the anonymous namespace. By default
  15.333 +# anonymous namespace are hidden.
  15.334 +
  15.335 +EXTRACT_ANON_NSPACES   = NO
  15.336 +
  15.337 +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
  15.338 +# undocumented members of documented classes, files or namespaces.
  15.339 +# If set to NO (the default) these members will be included in the
  15.340 +# various overviews, but no documentation section is generated.
  15.341 +# This option has no effect if EXTRACT_ALL is enabled.
  15.342 +
  15.343 +HIDE_UNDOC_MEMBERS     = NO
  15.344 +
  15.345 +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
  15.346 +# undocumented classes that are normally visible in the class hierarchy.
  15.347 +# If set to NO (the default) these classes will be included in the various
  15.348 +# overviews. This option has no effect if EXTRACT_ALL is enabled.
  15.349 +
  15.350 +HIDE_UNDOC_CLASSES     = NO
  15.351 +
  15.352 +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
  15.353 +# friend (class|struct|union) declarations.
  15.354 +# If set to NO (the default) these declarations will be included in the
  15.355 +# documentation.
  15.356 +
  15.357 +HIDE_FRIEND_COMPOUNDS  = NO
  15.358 +
  15.359 +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
  15.360 +# documentation blocks found inside the body of a function.
  15.361 +# If set to NO (the default) these blocks will be appended to the
  15.362 +# function's detailed documentation block.
  15.363 +
  15.364 +HIDE_IN_BODY_DOCS      = NO
  15.365 +
  15.366 +# The INTERNAL_DOCS tag determines if documentation
  15.367 +# that is typed after a \internal command is included. If the tag is set
  15.368 +# to NO (the default) then the documentation will be excluded.
  15.369 +# Set it to YES to include the internal documentation.
  15.370 +
  15.371 +INTERNAL_DOCS          = NO
  15.372 +
  15.373 +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
  15.374 +# file names in lower-case letters. If set to YES upper-case letters are also
  15.375 +# allowed. This is useful if you have classes or files whose names only differ
  15.376 +# in case and if your file system supports case sensitive file names. Windows
  15.377 +# and Mac users are advised to set this option to NO.
  15.378 +
  15.379 +CASE_SENSE_NAMES       = YES
  15.380 +
  15.381 +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
  15.382 +# will show members with their full class and namespace scopes in the
  15.383 +# documentation. If set to YES the scope will be hidden.
  15.384 +
  15.385 +HIDE_SCOPE_NAMES       = NO
  15.386 +
  15.387 +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
  15.388 +# will put a list of the files that are included by a file in the documentation
  15.389 +# of that file.
  15.390 +
  15.391 +SHOW_INCLUDE_FILES     = YES
  15.392 +
  15.393 +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
  15.394 +# will list include files with double quotes in the documentation
  15.395 +# rather than with sharp brackets.
  15.396 +
  15.397 +FORCE_LOCAL_INCLUDES   = NO
  15.398 +
  15.399 +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
  15.400 +# is inserted in the documentation for inline members.
  15.401 +
  15.402 +INLINE_INFO            = YES
  15.403 +
  15.404 +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
  15.405 +# will sort the (detailed) documentation of file and class members
  15.406 +# alphabetically by member name. If set to NO the members will appear in
  15.407 +# declaration order.
  15.408 +
  15.409 +SORT_MEMBER_DOCS       = YES
  15.410 +
  15.411 +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
  15.412 +# brief documentation of file, namespace and class members alphabetically
  15.413 +# by member name. If set to NO (the default) the members will appear in
  15.414 +# declaration order.
  15.415 +
  15.416 +SORT_BRIEF_DOCS        = NO
  15.417 +
  15.418 +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
  15.419 +# will sort the (brief and detailed) documentation of class members so that
  15.420 +# constructors and destructors are listed first. If set to NO (the default)
  15.421 +# the constructors will appear in the respective orders defined by
  15.422 +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
  15.423 +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
  15.424 +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
  15.425 +
  15.426 +SORT_MEMBERS_CTORS_1ST = NO
  15.427 +
  15.428 +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
  15.429 +# hierarchy of group names into alphabetical order. If set to NO (the default)
  15.430 +# the group names will appear in their defined order.
  15.431 +
  15.432 +SORT_GROUP_NAMES       = NO
  15.433 +
  15.434 +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
  15.435 +# sorted by fully-qualified names, including namespaces. If set to
  15.436 +# NO (the default), the class list will be sorted only by class name,
  15.437 +# not including the namespace part.
  15.438 +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
  15.439 +# Note: This option applies only to the class list, not to the
  15.440 +# alphabetical list.
  15.441 +
  15.442 +SORT_BY_SCOPE_NAME     = NO
  15.443 +
  15.444 +# The GENERATE_TODOLIST tag can be used to enable (YES) or
  15.445 +# disable (NO) the todo list. This list is created by putting \todo
  15.446 +# commands in the documentation.
  15.447 +
  15.448 +GENERATE_TODOLIST      = YES
  15.449 +
  15.450 +# The GENERATE_TESTLIST tag can be used to enable (YES) or
  15.451 +# disable (NO) the test list. This list is created by putting \test
  15.452 +# commands in the documentation.
  15.453 +
  15.454 +GENERATE_TESTLIST      = YES
  15.455 +
  15.456 +# The GENERATE_BUGLIST tag can be used to enable (YES) or
  15.457 +# disable (NO) the bug list. This list is created by putting \bug
  15.458 +# commands in the documentation.
  15.459 +
  15.460 +GENERATE_BUGLIST       = YES
  15.461 +
  15.462 +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
  15.463 +# disable (NO) the deprecated list. This list is created by putting
  15.464 +# \deprecated commands in the documentation.
  15.465 +
  15.466 +GENERATE_DEPRECATEDLIST= YES
  15.467 +
  15.468 +# The ENABLED_SECTIONS tag can be used to enable conditional
  15.469 +# documentation sections, marked by \if sectionname ... \endif.
  15.470 +
  15.471 +ENABLED_SECTIONS       =
  15.472 +
  15.473 +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
  15.474 +# the initial value of a variable or define consists of for it to appear in
  15.475 +# the documentation. If the initializer consists of more lines than specified
  15.476 +# here it will be hidden. Use a value of 0 to hide initializers completely.
  15.477 +# The appearance of the initializer of individual variables and defines in the
  15.478 +# documentation can be controlled using \showinitializer or \hideinitializer
  15.479 +# command in the documentation regardless of this setting.
  15.480 +
  15.481 +MAX_INITIALIZER_LINES  = 30
  15.482 +
  15.483 +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
  15.484 +# at the bottom of the documentation of classes and structs. If set to YES the
  15.485 +# list will mention the files that were used to generate the documentation.
  15.486 +
  15.487 +SHOW_USED_FILES        = YES
  15.488 +
  15.489 +# If the sources in your project are distributed over multiple directories
  15.490 +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
  15.491 +# in the documentation. The default is NO.
  15.492 +
  15.493 +SHOW_DIRECTORIES       = NO
  15.494 +
  15.495 +# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
  15.496 +# This will remove the Files entry from the Quick Index and from the
  15.497 +# Folder Tree View (if specified). The default is YES.
  15.498 +
  15.499 +SHOW_FILES             = YES
  15.500 +
  15.501 +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
  15.502 +# Namespaces page.
  15.503 +# This will remove the Namespaces entry from the Quick Index
  15.504 +# and from the Folder Tree View (if specified). The default is YES.
  15.505 +
  15.506 +SHOW_NAMESPACES        = YES
  15.507 +
  15.508 +# The FILE_VERSION_FILTER tag can be used to specify a program or script that
  15.509 +# doxygen should invoke to get the current version for each file (typically from
  15.510 +# the version control system). Doxygen will invoke the program by executing (via
  15.511 +# popen()) the command <command> <input-file>, where <command> is the value of
  15.512 +# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
  15.513 +# provided by doxygen. Whatever the program writes to standard output
  15.514 +# is used as the file version. See the manual for examples.
  15.515 +
  15.516 +FILE_VERSION_FILTER    =
  15.517 +
  15.518 +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
  15.519 +# by doxygen. The layout file controls the global structure of the generated
  15.520 +# output files in an output format independent way. The create the layout file
  15.521 +# that represents doxygen's defaults, run doxygen with the -l option.
  15.522 +# You can optionally specify a file name after the option, if omitted
  15.523 +# DoxygenLayout.xml will be used as the name of the layout file.
  15.524 +
  15.525 +LAYOUT_FILE            =
  15.526 +
  15.527 +#---------------------------------------------------------------------------
  15.528 +# configuration options related to warning and progress messages
  15.529 +#---------------------------------------------------------------------------
  15.530 +
  15.531 +# The QUIET tag can be used to turn on/off the messages that are generated
  15.532 +# by doxygen. Possible values are YES and NO. If left blank NO is used.
  15.533 +
  15.534 +QUIET                  = NO
  15.535 +
  15.536 +# The WARNINGS tag can be used to turn on/off the warning messages that are
  15.537 +# generated by doxygen. Possible values are YES and NO. If left blank
  15.538 +# NO is used.
  15.539 +
  15.540 +WARNINGS               = YES
  15.541 +
  15.542 +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
  15.543 +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
  15.544 +# automatically be disabled.
  15.545 +
  15.546 +WARN_IF_UNDOCUMENTED   = YES
  15.547 +
  15.548 +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
  15.549 +# potential errors in the documentation, such as not documenting some
  15.550 +# parameters in a documented function, or documenting parameters that
  15.551 +# don't exist or using markup commands wrongly.
  15.552 +
  15.553 +WARN_IF_DOC_ERROR      = YES
  15.554 +
  15.555 +# This WARN_NO_PARAMDOC option can be abled to get warnings for
  15.556 +# functions that are documented, but have no documentation for their parameters
  15.557 +# or return value. If set to NO (the default) doxygen will only warn about
  15.558 +# wrong or incomplete parameter documentation, but not about the absence of
  15.559 +# documentation.
  15.560 +
  15.561 +WARN_NO_PARAMDOC       = NO
  15.562 +
  15.563 +# The WARN_FORMAT tag determines the format of the warning messages that
  15.564 +# doxygen can produce. The string should contain the $file, $line, and $text
  15.565 +# tags, which will be replaced by the file and line number from which the
  15.566 +# warning originated and the warning text. Optionally the format may contain
  15.567 +# $version, which will be replaced by the version of the file (if it could
  15.568 +# be obtained via FILE_VERSION_FILTER)
  15.569 +
  15.570 +WARN_FORMAT            = "$file:$line: $text"
  15.571 +
  15.572 +# The WARN_LOGFILE tag can be used to specify a file to which warning
  15.573 +# and error messages should be written. If left blank the output is written
  15.574 +# to stderr.
  15.575 +
  15.576 +WARN_LOGFILE           =
  15.577 +
  15.578 +#---------------------------------------------------------------------------
  15.579 +# configuration options related to the input files
  15.580 +#---------------------------------------------------------------------------
  15.581 +
  15.582 +# The INPUT tag can be used to specify the files and/or directories that contain
  15.583 +# documented source files. You may enter file names like "myfile.cpp" or
  15.584 +# directories like "/usr/src/myproject". Separate the files or directories
  15.585 +# with spaces.
  15.586 +
  15.587 +INPUT                  = ../hidapi
  15.588 +
  15.589 +# This tag can be used to specify the character encoding of the source files
  15.590 +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
  15.591 +# also the default input encoding. Doxygen uses libiconv (or the iconv built
  15.592 +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
  15.593 +# the list of possible encodings.
  15.594 +
  15.595 +INPUT_ENCODING         = UTF-8
  15.596 +
  15.597 +# If the value of the INPUT tag contains directories, you can use the
  15.598 +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
  15.599 +# and *.h) to filter out the source-files in the directories. If left
  15.600 +# blank the following patterns are tested:
  15.601 +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
  15.602 +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
  15.603 +
  15.604 +FILE_PATTERNS          =
  15.605 +
  15.606 +# The RECURSIVE tag can be used to turn specify whether or not subdirectories
  15.607 +# should be searched for input files as well. Possible values are YES and NO.
  15.608 +# If left blank NO is used.
  15.609 +
  15.610 +RECURSIVE              = NO
  15.611 +
  15.612 +# The EXCLUDE tag can be used to specify files and/or directories that should
  15.613 +# excluded from the INPUT source files. This way you can easily exclude a
  15.614 +# subdirectory from a directory tree whose root is specified with the INPUT tag.
  15.615 +
  15.616 +EXCLUDE                =
  15.617 +
  15.618 +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
  15.619 +# directories that are symbolic links (a Unix filesystem feature) are excluded
  15.620 +# from the input.
  15.621 +
  15.622 +EXCLUDE_SYMLINKS       = NO
  15.623 +
  15.624 +# If the value of the INPUT tag contains directories, you can use the
  15.625 +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
  15.626 +# certain files from those directories. Note that the wildcards are matched
  15.627 +# against the file with absolute path, so to exclude all test directories
  15.628 +# for example use the pattern */test/*
  15.629 +
  15.630 +EXCLUDE_PATTERNS       =
  15.631 +
  15.632 +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
  15.633 +# (namespaces, classes, functions, etc.) that should be excluded from the
  15.634 +# output. The symbol name can be a fully qualified name, a word, or if the
  15.635 +# wildcard * is used, a substring. Examples: ANamespace, AClass,
  15.636 +# AClass::ANamespace, ANamespace::*Test
  15.637 +
  15.638 +EXCLUDE_SYMBOLS        =
  15.639 +
  15.640 +# The EXAMPLE_PATH tag can be used to specify one or more files or
  15.641 +# directories that contain example code fragments that are included (see
  15.642 +# the \include command).
  15.643 +
  15.644 +EXAMPLE_PATH           =
  15.645 +
  15.646 +# If the value of the EXAMPLE_PATH tag contains directories, you can use the
  15.647 +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
  15.648 +# and *.h) to filter out the source-files in the directories. If left
  15.649 +# blank all files are included.
  15.650 +
  15.651 +EXAMPLE_PATTERNS       =
  15.652 +
  15.653 +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
  15.654 +# searched for input files to be used with the \include or \dontinclude
  15.655 +# commands irrespective of the value of the RECURSIVE tag.
  15.656 +# Possible values are YES and NO. If left blank NO is used.
  15.657 +
  15.658 +EXAMPLE_RECURSIVE      = NO
  15.659 +
  15.660 +# The IMAGE_PATH tag can be used to specify one or more files or
  15.661 +# directories that contain image that are included in the documentation (see
  15.662 +# the \image command).
  15.663 +
  15.664 +IMAGE_PATH             =
  15.665 +
  15.666 +# The INPUT_FILTER tag can be used to specify a program that doxygen should
  15.667 +# invoke to filter for each input file. Doxygen will invoke the filter program
  15.668 +# by executing (via popen()) the command <filter> <input-file>, where <filter>
  15.669 +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
  15.670 +# input file. Doxygen will then use the output that the filter program writes
  15.671 +# to standard output.
  15.672 +# If FILTER_PATTERNS is specified, this tag will be
  15.673 +# ignored.
  15.674 +
  15.675 +INPUT_FILTER           =
  15.676 +
  15.677 +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
  15.678 +# basis.
  15.679 +# Doxygen will compare the file name with each pattern and apply the
  15.680 +# filter if there is a match.
  15.681 +# The filters are a list of the form:
  15.682 +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
  15.683 +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
  15.684 +# is applied to all files.
  15.685 +
  15.686 +FILTER_PATTERNS        =
  15.687 +
  15.688 +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
  15.689 +# INPUT_FILTER) will be used to filter the input files when producing source
  15.690 +# files to browse (i.e. when SOURCE_BROWSER is set to YES).
  15.691 +
  15.692 +FILTER_SOURCE_FILES    = NO
  15.693 +
  15.694 +#---------------------------------------------------------------------------
  15.695 +# configuration options related to source browsing
  15.696 +#---------------------------------------------------------------------------
  15.697 +
  15.698 +# If the SOURCE_BROWSER tag is set to YES then a list of source files will
  15.699 +# be generated. Documented entities will be cross-referenced with these sources.
  15.700 +# Note: To get rid of all source code in the generated output, make sure also
  15.701 +# VERBATIM_HEADERS is set to NO.
  15.702 +
  15.703 +SOURCE_BROWSER         = NO
  15.704 +
  15.705 +# Setting the INLINE_SOURCES tag to YES will include the body
  15.706 +# of functions and classes directly in the documentation.
  15.707 +
  15.708 +INLINE_SOURCES         = NO
  15.709 +
  15.710 +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
  15.711 +# doxygen to hide any special comment blocks from generated source code
  15.712 +# fragments. Normal C and C++ comments will always remain visible.
  15.713 +
  15.714 +STRIP_CODE_COMMENTS    = YES
  15.715 +
  15.716 +# If the REFERENCED_BY_RELATION tag is set to YES
  15.717 +# then for each documented function all documented
  15.718 +# functions referencing it will be listed.
  15.719 +
  15.720 +REFERENCED_BY_RELATION = NO
  15.721 +
  15.722 +# If the REFERENCES_RELATION tag is set to YES
  15.723 +# then for each documented function all documented entities
  15.724 +# called/used by that function will be listed.
  15.725 +
  15.726 +REFERENCES_RELATION    = NO
  15.727 +
  15.728 +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
  15.729 +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
  15.730 +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
  15.731 +# link to the source code.
  15.732 +# Otherwise they will link to the documentation.
  15.733 +
  15.734 +REFERENCES_LINK_SOURCE = YES
  15.735 +
  15.736 +# If the USE_HTAGS tag is set to YES then the references to source code
  15.737 +# will point to the HTML generated by the htags(1) tool instead of doxygen
  15.738 +# built-in source browser. The htags tool is part of GNU's global source
  15.739 +# tagging system (see http://www.gnu.org/software/global/global.html). You
  15.740 +# will need version 4.8.6 or higher.
  15.741 +
  15.742 +USE_HTAGS              = NO
  15.743 +
  15.744 +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
  15.745 +# will generate a verbatim copy of the header file for each class for
  15.746 +# which an include is specified. Set to NO to disable this.
  15.747 +
  15.748 +VERBATIM_HEADERS       = YES
  15.749 +
  15.750 +#---------------------------------------------------------------------------
  15.751 +# configuration options related to the alphabetical class index
  15.752 +#---------------------------------------------------------------------------
  15.753 +
  15.754 +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
  15.755 +# of all compounds will be generated. Enable this if the project
  15.756 +# contains a lot of classes, structs, unions or interfaces.
  15.757 +
  15.758 +ALPHABETICAL_INDEX     = YES
  15.759 +
  15.760 +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
  15.761 +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
  15.762 +# in which this list will be split (can be a number in the range [1..20])
  15.763 +
  15.764 +COLS_IN_ALPHA_INDEX    = 5
  15.765 +
  15.766 +# In case all classes in a project start with a common prefix, all
  15.767 +# classes will be put under the same header in the alphabetical index.
  15.768 +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
  15.769 +# should be ignored while generating the index headers.
  15.770 +
  15.771 +IGNORE_PREFIX          =
  15.772 +
  15.773 +#---------------------------------------------------------------------------
  15.774 +# configuration options related to the HTML output
  15.775 +#---------------------------------------------------------------------------
  15.776 +
  15.777 +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
  15.778 +# generate HTML output.
  15.779 +
  15.780 +GENERATE_HTML          = YES
  15.781 +
  15.782 +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
  15.783 +# If a relative path is entered the value of OUTPUT_DIRECTORY will be
  15.784 +# put in front of it. If left blank `html' will be used as the default path.
  15.785 +
  15.786 +HTML_OUTPUT            = html
  15.787 +
  15.788 +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
  15.789 +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
  15.790 +# doxygen will generate files with .html extension.
  15.791 +
  15.792 +HTML_FILE_EXTENSION    = .html
  15.793 +
  15.794 +# The HTML_HEADER tag can be used to specify a personal HTML header for
  15.795 +# each generated HTML page. If it is left blank doxygen will generate a
  15.796 +# standard header.
  15.797 +
  15.798 +HTML_HEADER            =
  15.799 +
  15.800 +# The HTML_FOOTER tag can be used to specify a personal HTML footer for
  15.801 +# each generated HTML page. If it is left blank doxygen will generate a
  15.802 +# standard footer.
  15.803 +
  15.804 +HTML_FOOTER            =
  15.805 +
  15.806 +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
  15.807 +# style sheet that is used by each HTML page. It can be used to
  15.808 +# fine-tune the look of the HTML output. If the tag is left blank doxygen
  15.809 +# will generate a default style sheet. Note that doxygen will try to copy
  15.810 +# the style sheet file to the HTML output directory, so don't put your own
  15.811 +# stylesheet in the HTML output directory as well, or it will be erased!
  15.812 +
  15.813 +HTML_STYLESHEET        =
  15.814 +
  15.815 +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
  15.816 +# Doxygen will adjust the colors in the stylesheet and background images
  15.817 +# according to this color. Hue is specified as an angle on a colorwheel,
  15.818 +# see http://en.wikipedia.org/wiki/Hue for more information.
  15.819 +# For instance the value 0 represents red, 60 is yellow, 120 is green,
  15.820 +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
  15.821 +# The allowed range is 0 to 359.
  15.822 +
  15.823 +HTML_COLORSTYLE_HUE    = 220
  15.824 +
  15.825 +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
  15.826 +# the colors in the HTML output. For a value of 0 the output will use
  15.827 +# grayscales only. A value of 255 will produce the most vivid colors.
  15.828 +
  15.829 +HTML_COLORSTYLE_SAT    = 100
  15.830 +
  15.831 +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
  15.832 +# the luminance component of the colors in the HTML output. Values below
  15.833 +# 100 gradually make the output lighter, whereas values above 100 make
  15.834 +# the output darker. The value divided by 100 is the actual gamma applied,
  15.835 +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
  15.836 +# and 100 does not change the gamma.
  15.837 +
  15.838 +HTML_COLORSTYLE_GAMMA  = 80
  15.839 +
  15.840 +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
  15.841 +# page will contain the date and time when the page was generated. Setting
  15.842 +# this to NO can help when comparing the output of multiple runs.
  15.843 +
  15.844 +HTML_TIMESTAMP         = YES
  15.845 +
  15.846 +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
  15.847 +# files or namespaces will be aligned in HTML using tables. If set to
  15.848 +# NO a bullet list will be used.
  15.849 +
  15.850 +HTML_ALIGN_MEMBERS     = YES
  15.851 +
  15.852 +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
  15.853 +# documentation will contain sections that can be hidden and shown after the
  15.854 +# page has loaded. For this to work a browser that supports
  15.855 +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
  15.856 +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
  15.857 +
  15.858 +HTML_DYNAMIC_SECTIONS  = NO
  15.859 +
  15.860 +# If the GENERATE_DOCSET tag is set to YES, additional index files
  15.861 +# will be generated that can be used as input for Apple's Xcode 3
  15.862 +# integrated development environment, introduced with OSX 10.5 (Leopard).
  15.863 +# To create a documentation set, doxygen will generate a Makefile in the
  15.864 +# HTML output directory. Running make will produce the docset in that
  15.865 +# directory and running "make install" will install the docset in
  15.866 +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
  15.867 +# it at startup.
  15.868 +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
  15.869 +# for more information.
  15.870 +
  15.871 +GENERATE_DOCSET        = NO
  15.872 +
  15.873 +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
  15.874 +# feed. A documentation feed provides an umbrella under which multiple
  15.875 +# documentation sets from a single provider (such as a company or product suite)
  15.876 +# can be grouped.
  15.877 +
  15.878 +DOCSET_FEEDNAME        = "Doxygen generated docs"
  15.879 +
  15.880 +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
  15.881 +# should uniquely identify the documentation set bundle. This should be a
  15.882 +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
  15.883 +# will append .docset to the name.
  15.884 +
  15.885 +DOCSET_BUNDLE_ID       = org.doxygen.Project
  15.886 +
  15.887 +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
  15.888 +# the documentation publisher. This should be a reverse domain-name style
  15.889 +# string, e.g. com.mycompany.MyDocSet.documentation.
  15.890 +
  15.891 +DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
  15.892 +
  15.893 +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
  15.894 +
  15.895 +DOCSET_PUBLISHER_NAME  = Publisher
  15.896 +
  15.897 +# If the GENERATE_HTMLHELP tag is set to YES, additional index files
  15.898 +# will be generated that can be used as input for tools like the
  15.899 +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
  15.900 +# of the generated HTML documentation.
  15.901 +
  15.902 +GENERATE_HTMLHELP      = NO
  15.903 +
  15.904 +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
  15.905 +# be used to specify the file name of the resulting .chm file. You
  15.906 +# can add a path in front of the file if the result should not be
  15.907 +# written to the html output directory.
  15.908 +
  15.909 +CHM_FILE               =
  15.910 +
  15.911 +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
  15.912 +# be used to specify the location (absolute path including file name) of
  15.913 +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
  15.914 +# the HTML help compiler on the generated index.hhp.
  15.915 +
  15.916 +HHC_LOCATION           =
  15.917 +
  15.918 +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
  15.919 +# controls if a separate .chi index file is generated (YES) or that
  15.920 +# it should be included in the master .chm file (NO).
  15.921 +
  15.922 +GENERATE_CHI           = NO
  15.923 +
  15.924 +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
  15.925 +# is used to encode HtmlHelp index (hhk), content (hhc) and project file
  15.926 +# content.
  15.927 +
  15.928 +CHM_INDEX_ENCODING     =
  15.929 +
  15.930 +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
  15.931 +# controls whether a binary table of contents is generated (YES) or a
  15.932 +# normal table of contents (NO) in the .chm file.
  15.933 +
  15.934 +BINARY_TOC             = NO
  15.935 +
  15.936 +# The TOC_EXPAND flag can be set to YES to add extra items for group members
  15.937 +# to the contents of the HTML help documentation and to the tree view.
  15.938 +
  15.939 +TOC_EXPAND             = NO
  15.940 +
  15.941 +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
  15.942 +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
  15.943 +# that can be used as input for Qt's qhelpgenerator to generate a
  15.944 +# Qt Compressed Help (.qch) of the generated HTML documentation.
  15.945 +
  15.946 +GENERATE_QHP           = NO
  15.947 +
  15.948 +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
  15.949 +# be used to specify the file name of the resulting .qch file.
  15.950 +# The path specified is relative to the HTML output folder.
  15.951 +
  15.952 +QCH_FILE               =
  15.953 +
  15.954 +# The QHP_NAMESPACE tag specifies the namespace to use when generating
  15.955 +# Qt Help Project output. For more information please see
  15.956 +# http://doc.trolltech.com/qthelpproject.html#namespace
  15.957 +
  15.958 +QHP_NAMESPACE          = org.doxygen.Project
  15.959 +
  15.960 +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
  15.961 +# Qt Help Project output. For more information please see
  15.962 +# http://doc.trolltech.com/qthelpproject.html#virtual-folders
  15.963 +
  15.964 +QHP_VIRTUAL_FOLDER     = doc
  15.965 +
  15.966 +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
  15.967 +# add. For more information please see
  15.968 +# http://doc.trolltech.com/qthelpproject.html#custom-filters
  15.969 +
  15.970 +QHP_CUST_FILTER_NAME   =
  15.971 +
  15.972 +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
  15.973 +# custom filter to add. For more information please see
  15.974 +# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
  15.975 +# Qt Help Project / Custom Filters</a>.
  15.976 +
  15.977 +QHP_CUST_FILTER_ATTRS  =
  15.978 +
  15.979 +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
  15.980 +# project's
  15.981 +# filter section matches.
  15.982 +# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
  15.983 +# Qt Help Project / Filter Attributes</a>.
  15.984 +
  15.985 +QHP_SECT_FILTER_ATTRS  =
  15.986 +
  15.987 +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
  15.988 +# be used to specify the location of Qt's qhelpgenerator.
  15.989 +# If non-empty doxygen will try to run qhelpgenerator on the generated
  15.990 +# .qhp file.
  15.991 +
  15.992 +QHG_LOCATION           =
  15.993 +
  15.994 +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
  15.995 +#  will be generated, which together with the HTML files, form an Eclipse help
  15.996 +# plugin. To install this plugin and make it available under the help contents
  15.997 +# menu in Eclipse, the contents of the directory containing the HTML and XML
  15.998 +# files needs to be copied into the plugins directory of eclipse. The name of
  15.999 +# the directory within the plugins directory should be the same as
 15.1000 +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
 15.1001 +# the help appears.
 15.1002 +
 15.1003 +GENERATE_ECLIPSEHELP   = NO
 15.1004 +
 15.1005 +# A unique identifier for the eclipse help plugin. When installing the plugin
 15.1006 +# the directory name containing the HTML and XML files should also have
 15.1007 +# this name.
 15.1008 +
 15.1009 +ECLIPSE_DOC_ID         = org.doxygen.Project
 15.1010 +
 15.1011 +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
 15.1012 +# top of each HTML page. The value NO (the default) enables the index and
 15.1013 +# the value YES disables it.
 15.1014 +
 15.1015 +DISABLE_INDEX          = NO
 15.1016 +
 15.1017 +# This tag can be used to set the number of enum values (range [1..20])
 15.1018 +# that doxygen will group on one line in the generated HTML documentation.
 15.1019 +
 15.1020 +ENUM_VALUES_PER_LINE   = 4
 15.1021 +
 15.1022 +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
 15.1023 +# structure should be generated to display hierarchical information.
 15.1024 +# If the tag value is set to YES, a side panel will be generated
 15.1025 +# containing a tree-like index structure (just like the one that
 15.1026 +# is generated for HTML Help). For this to work a browser that supports
 15.1027 +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
 15.1028 +# Windows users are probably better off using the HTML help feature.
 15.1029 +
 15.1030 +GENERATE_TREEVIEW      = NO
 15.1031 +
 15.1032 +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
 15.1033 +# and Class Hierarchy pages using a tree view instead of an ordered list.
 15.1034 +
 15.1035 +USE_INLINE_TREES       = NO
 15.1036 +
 15.1037 +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
 15.1038 +# used to set the initial width (in pixels) of the frame in which the tree
 15.1039 +# is shown.
 15.1040 +
 15.1041 +TREEVIEW_WIDTH         = 250
 15.1042 +
 15.1043 +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
 15.1044 +# links to external symbols imported via tag files in a separate window.
 15.1045 +
 15.1046 +EXT_LINKS_IN_WINDOW    = NO
 15.1047 +
 15.1048 +# Use this tag to change the font size of Latex formulas included
 15.1049 +# as images in the HTML documentation. The default is 10. Note that
 15.1050 +# when you change the font size after a successful doxygen run you need
 15.1051 +# to manually remove any form_*.png images from the HTML output directory
 15.1052 +# to force them to be regenerated.
 15.1053 +
 15.1054 +FORMULA_FONTSIZE       = 10
 15.1055 +
 15.1056 +# Use the FORMULA_TRANPARENT tag to determine whether or not the images
 15.1057 +# generated for formulas are transparent PNGs. Transparent PNGs are
 15.1058 +# not supported properly for IE 6.0, but are supported on all modern browsers.
 15.1059 +# Note that when changing this option you need to delete any form_*.png files
 15.1060 +# in the HTML output before the changes have effect.
 15.1061 +
 15.1062 +FORMULA_TRANSPARENT    = YES
 15.1063 +
 15.1064 +# When the SEARCHENGINE tag is enabled doxygen will generate a search box
 15.1065 +# for the HTML output. The underlying search engine uses javascript
 15.1066 +# and DHTML and should work on any modern browser. Note that when using
 15.1067 +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
 15.1068 +# (GENERATE_DOCSET) there is already a search function so this one should
 15.1069 +# typically be disabled. For large projects the javascript based search engine
 15.1070 +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
 15.1071 +
 15.1072 +SEARCHENGINE           = YES
 15.1073 +
 15.1074 +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
 15.1075 +# implemented using a PHP enabled web server instead of at the web client
 15.1076 +# using Javascript. Doxygen will generate the search PHP script and index
 15.1077 +# file to put on the web server. The advantage of the server
 15.1078 +# based approach is that it scales better to large projects and allows
 15.1079 +# full text search. The disadvances is that it is more difficult to setup
 15.1080 +# and does not have live searching capabilities.
 15.1081 +
 15.1082 +SERVER_BASED_SEARCH    = NO
 15.1083 +
 15.1084 +#---------------------------------------------------------------------------
 15.1085 +# configuration options related to the LaTeX output
 15.1086 +#---------------------------------------------------------------------------
 15.1087 +
 15.1088 +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
 15.1089 +# generate Latex output.
 15.1090 +
 15.1091 +GENERATE_LATEX         = NO
 15.1092 +
 15.1093 +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
 15.1094 +# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 15.1095 +# put in front of it. If left blank `latex' will be used as the default path.
 15.1096 +
 15.1097 +LATEX_OUTPUT           = latex
 15.1098 +
 15.1099 +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
 15.1100 +# invoked. If left blank `latex' will be used as the default command name.
 15.1101 +# Note that when enabling USE_PDFLATEX this option is only used for
 15.1102 +# generating bitmaps for formulas in the HTML output, but not in the
 15.1103 +# Makefile that is written to the output directory.
 15.1104 +
 15.1105 +LATEX_CMD_NAME         = latex
 15.1106 +
 15.1107 +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
 15.1108 +# generate index for LaTeX. If left blank `makeindex' will be used as the
 15.1109 +# default command name.
 15.1110 +
 15.1111 +MAKEINDEX_CMD_NAME     = makeindex
 15.1112 +
 15.1113 +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
 15.1114 +# LaTeX documents. This may be useful for small projects and may help to
 15.1115 +# save some trees in general.
 15.1116 +
 15.1117 +COMPACT_LATEX          = NO
 15.1118 +
 15.1119 +# The PAPER_TYPE tag can be used to set the paper type that is used
 15.1120 +# by the printer. Possible values are: a4, a4wide, letter, legal and
 15.1121 +# executive. If left blank a4wide will be used.
 15.1122 +
 15.1123 +PAPER_TYPE             = a4wide
 15.1124 +
 15.1125 +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
 15.1126 +# packages that should be included in the LaTeX output.
 15.1127 +
 15.1128 +EXTRA_PACKAGES         =
 15.1129 +
 15.1130 +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
 15.1131 +# the generated latex document. The header should contain everything until
 15.1132 +# the first chapter. If it is left blank doxygen will generate a
 15.1133 +# standard header. Notice: only use this tag if you know what you are doing!
 15.1134 +
 15.1135 +LATEX_HEADER           =
 15.1136 +
 15.1137 +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
 15.1138 +# is prepared for conversion to pdf (using ps2pdf). The pdf file will
 15.1139 +# contain links (just like the HTML output) instead of page references
 15.1140 +# This makes the output suitable for online browsing using a pdf viewer.
 15.1141 +
 15.1142 +PDF_HYPERLINKS         = YES
 15.1143 +
 15.1144 +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
 15.1145 +# plain latex in the generated Makefile. Set this option to YES to get a
 15.1146 +# higher quality PDF documentation.
 15.1147 +
 15.1148 +USE_PDFLATEX           = YES
 15.1149 +
 15.1150 +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
 15.1151 +# command to the generated LaTeX files. This will instruct LaTeX to keep
 15.1152 +# running if errors occur, instead of asking the user for help.
 15.1153 +# This option is also used when generating formulas in HTML.
 15.1154 +
 15.1155 +LATEX_BATCHMODE        = NO
 15.1156 +
 15.1157 +# If LATEX_HIDE_INDICES is set to YES then doxygen will not
 15.1158 +# include the index chapters (such as File Index, Compound Index, etc.)
 15.1159 +# in the output.
 15.1160 +
 15.1161 +LATEX_HIDE_INDICES     = NO
 15.1162 +
 15.1163 +# If LATEX_SOURCE_CODE is set to YES then doxygen will include
 15.1164 +# source code with syntax highlighting in the LaTeX output.
 15.1165 +# Note that which sources are shown also depends on other settings
 15.1166 +# such as SOURCE_BROWSER.
 15.1167 +
 15.1168 +LATEX_SOURCE_CODE      = NO
 15.1169 +
 15.1170 +#---------------------------------------------------------------------------
 15.1171 +# configuration options related to the RTF output
 15.1172 +#---------------------------------------------------------------------------
 15.1173 +
 15.1174 +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
 15.1175 +# The RTF output is optimized for Word 97 and may not look very pretty with
 15.1176 +# other RTF readers or editors.
 15.1177 +
 15.1178 +GENERATE_RTF           = NO
 15.1179 +
 15.1180 +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
 15.1181 +# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 15.1182 +# put in front of it. If left blank `rtf' will be used as the default path.
 15.1183 +
 15.1184 +RTF_OUTPUT             = rtf
 15.1185 +
 15.1186 +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
 15.1187 +# RTF documents. This may be useful for small projects and may help to
 15.1188 +# save some trees in general.
 15.1189 +
 15.1190 +COMPACT_RTF            = NO
 15.1191 +
 15.1192 +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
 15.1193 +# will contain hyperlink fields. The RTF file will
 15.1194 +# contain links (just like the HTML output) instead of page references.
 15.1195 +# This makes the output suitable for online browsing using WORD or other
 15.1196 +# programs which support those fields.
 15.1197 +# Note: wordpad (write) and others do not support links.
 15.1198 +
 15.1199 +RTF_HYPERLINKS         = NO
 15.1200 +
 15.1201 +# Load stylesheet definitions from file. Syntax is similar to doxygen's
 15.1202 +# config file, i.e. a series of assignments. You only have to provide
 15.1203 +# replacements, missing definitions are set to their default value.
 15.1204 +
 15.1205 +RTF_STYLESHEET_FILE    =
 15.1206 +
 15.1207 +# Set optional variables used in the generation of an rtf document.
 15.1208 +# Syntax is similar to doxygen's config file.
 15.1209 +
 15.1210 +RTF_EXTENSIONS_FILE    =
 15.1211 +
 15.1212 +#---------------------------------------------------------------------------
 15.1213 +# configuration options related to the man page output
 15.1214 +#---------------------------------------------------------------------------
 15.1215 +
 15.1216 +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
 15.1217 +# generate man pages
 15.1218 +
 15.1219 +GENERATE_MAN           = NO
 15.1220 +
 15.1221 +# The MAN_OUTPUT tag is used to specify where the man pages will be put.
 15.1222 +# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 15.1223 +# put in front of it. If left blank `man' will be used as the default path.
 15.1224 +
 15.1225 +MAN_OUTPUT             = man
 15.1226 +
 15.1227 +# The MAN_EXTENSION tag determines the extension that is added to
 15.1228 +# the generated man pages (default is the subroutine's section .3)
 15.1229 +
 15.1230 +MAN_EXTENSION          = .3
 15.1231 +
 15.1232 +# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
 15.1233 +# then it will generate one additional man file for each entity
 15.1234 +# documented in the real man page(s). These additional files
 15.1235 +# only source the real man page, but without them the man command
 15.1236 +# would be unable to find the correct page. The default is NO.
 15.1237 +
 15.1238 +MAN_LINKS              = NO
 15.1239 +
 15.1240 +#---------------------------------------------------------------------------
 15.1241 +# configuration options related to the XML output
 15.1242 +#---------------------------------------------------------------------------
 15.1243 +
 15.1244 +# If the GENERATE_XML tag is set to YES Doxygen will
 15.1245 +# generate an XML file that captures the structure of
 15.1246 +# the code including all documentation.
 15.1247 +
 15.1248 +GENERATE_XML           = NO
 15.1249 +
 15.1250 +# The XML_OUTPUT tag is used to specify where the XML pages will be put.
 15.1251 +# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 15.1252 +# put in front of it. If left blank `xml' will be used as the default path.
 15.1253 +
 15.1254 +XML_OUTPUT             = xml
 15.1255 +
 15.1256 +# The XML_SCHEMA tag can be used to specify an XML schema,
 15.1257 +# which can be used by a validating XML parser to check the
 15.1258 +# syntax of the XML files.
 15.1259 +
 15.1260 +XML_SCHEMA             =
 15.1261 +
 15.1262 +# The XML_DTD tag can be used to specify an XML DTD,
 15.1263 +# which can be used by a validating XML parser to check the
 15.1264 +# syntax of the XML files.
 15.1265 +
 15.1266 +XML_DTD                =
 15.1267 +
 15.1268 +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
 15.1269 +# dump the program listings (including syntax highlighting
 15.1270 +# and cross-referencing information) to the XML output. Note that
 15.1271 +# enabling this will significantly increase the size of the XML output.
 15.1272 +
 15.1273 +XML_PROGRAMLISTING     = YES
 15.1274 +
 15.1275 +#---------------------------------------------------------------------------
 15.1276 +# configuration options for the AutoGen Definitions output
 15.1277 +#---------------------------------------------------------------------------
 15.1278 +
 15.1279 +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
 15.1280 +# generate an AutoGen Definitions (see autogen.sf.net) file
 15.1281 +# that captures the structure of the code including all
 15.1282 +# documentation. Note that this feature is still experimental
 15.1283 +# and incomplete at the moment.
 15.1284 +
 15.1285 +GENERATE_AUTOGEN_DEF   = NO
 15.1286 +
 15.1287 +#---------------------------------------------------------------------------
 15.1288 +# configuration options related to the Perl module output
 15.1289 +#---------------------------------------------------------------------------
 15.1290 +
 15.1291 +# If the GENERATE_PERLMOD tag is set to YES Doxygen will
 15.1292 +# generate a Perl module file that captures the structure of
 15.1293 +# the code including all documentation. Note that this
 15.1294 +# feature is still experimental and incomplete at the
 15.1295 +# moment.
 15.1296 +
 15.1297 +GENERATE_PERLMOD       = NO
 15.1298 +
 15.1299 +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
 15.1300 +# the necessary Makefile rules, Perl scripts and LaTeX code to be able
 15.1301 +# to generate PDF and DVI output from the Perl module output.
 15.1302 +
 15.1303 +PERLMOD_LATEX          = NO
 15.1304 +
 15.1305 +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
 15.1306 +# nicely formatted so it can be parsed by a human reader.
 15.1307 +# This is useful
 15.1308 +# if you want to understand what is going on.
 15.1309 +# On the other hand, if this
 15.1310 +# tag is set to NO the size of the Perl module output will be much smaller
 15.1311 +# and Perl will parse it just the same.
 15.1312 +
 15.1313 +PERLMOD_PRETTY         = YES
 15.1314 +
 15.1315 +# The names of the make variables in the generated doxyrules.make file
 15.1316 +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
 15.1317 +# This is useful so different doxyrules.make files included by the same
 15.1318 +# Makefile don't overwrite each other's variables.
 15.1319 +
 15.1320 +PERLMOD_MAKEVAR_PREFIX =
 15.1321 +
 15.1322 +#---------------------------------------------------------------------------
 15.1323 +# Configuration options related to the preprocessor
 15.1324 +#---------------------------------------------------------------------------
 15.1325 +
 15.1326 +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
 15.1327 +# evaluate all C-preprocessor directives found in the sources and include
 15.1328 +# files.
 15.1329 +
 15.1330 +ENABLE_PREPROCESSING   = YES
 15.1331 +
 15.1332 +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
 15.1333 +# names in the source code. If set to NO (the default) only conditional
 15.1334 +# compilation will be performed. Macro expansion can be done in a controlled
 15.1335 +# way by setting EXPAND_ONLY_PREDEF to YES.
 15.1336 +
 15.1337 +MACRO_EXPANSION        = NO
 15.1338 +
 15.1339 +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
 15.1340 +# then the macro expansion is limited to the macros specified with the
 15.1341 +# PREDEFINED and EXPAND_AS_DEFINED tags.
 15.1342 +
 15.1343 +EXPAND_ONLY_PREDEF     = NO
 15.1344 +
 15.1345 +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
 15.1346 +# in the INCLUDE_PATH (see below) will be search if a #include is found.
 15.1347 +
 15.1348 +SEARCH_INCLUDES        = YES
 15.1349 +
 15.1350 +# The INCLUDE_PATH tag can be used to specify one or more directories that
 15.1351 +# contain include files that are not input files but should be processed by
 15.1352 +# the preprocessor.
 15.1353 +
 15.1354 +INCLUDE_PATH           =
 15.1355 +
 15.1356 +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
 15.1357 +# patterns (like *.h and *.hpp) to filter out the header-files in the
 15.1358 +# directories. If left blank, the patterns specified with FILE_PATTERNS will
 15.1359 +# be used.
 15.1360 +
 15.1361 +INCLUDE_FILE_PATTERNS  =
 15.1362 +
 15.1363 +# The PREDEFINED tag can be used to specify one or more macro names that
 15.1364 +# are defined before the preprocessor is started (similar to the -D option of
 15.1365 +# gcc). The argument of the tag is a list of macros of the form: name
 15.1366 +# or name=definition (no spaces). If the definition and the = are
 15.1367 +# omitted =1 is assumed. To prevent a macro definition from being
 15.1368 +# undefined via #undef or recursively expanded use the := operator
 15.1369 +# instead of the = operator.
 15.1370 +
 15.1371 +PREDEFINED             =
 15.1372 +
 15.1373 +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
 15.1374 +# this tag can be used to specify a list of macro names that should be expanded.
 15.1375 +# The macro definition that is found in the sources will be used.
 15.1376 +# Use the PREDEFINED tag if you want to use a different macro definition.
 15.1377 +
 15.1378 +EXPAND_AS_DEFINED      =
 15.1379 +
 15.1380 +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
 15.1381 +# doxygen's preprocessor will remove all function-like macros that are alone
 15.1382 +# on a line, have an all uppercase name, and do not end with a semicolon. Such
 15.1383 +# function macros are typically used for boiler-plate code, and will confuse
 15.1384 +# the parser if not removed.
 15.1385 +
 15.1386 +SKIP_FUNCTION_MACROS   = YES
 15.1387 +
 15.1388 +#---------------------------------------------------------------------------
 15.1389 +# Configuration::additions related to external references
 15.1390 +#---------------------------------------------------------------------------
 15.1391 +
 15.1392 +# The TAGFILES option can be used to specify one or more tagfiles.
 15.1393 +# Optionally an initial location of the external documentation
 15.1394 +# can be added for each tagfile. The format of a tag file without
 15.1395 +# this location is as follows:
 15.1396 +#
 15.1397 +# TAGFILES = file1 file2 ...
 15.1398 +# Adding location for the tag files is done as follows:
 15.1399 +#
 15.1400 +# TAGFILES = file1=loc1 "file2 = loc2" ...
 15.1401 +# where "loc1" and "loc2" can be relative or absolute paths or
 15.1402 +# URLs. If a location is present for each tag, the installdox tool
 15.1403 +# does not have to be run to correct the links.
 15.1404 +# Note that each tag file must have a unique name
 15.1405 +# (where the name does NOT include the path)
 15.1406 +# If a tag file is not located in the directory in which doxygen
 15.1407 +# is run, you must also specify the path to the tagfile here.
 15.1408 +
 15.1409 +TAGFILES               =
 15.1410 +
 15.1411 +# When a file name is specified after GENERATE_TAGFILE, doxygen will create
 15.1412 +# a tag file that is based on the input files it reads.
 15.1413 +
 15.1414 +GENERATE_TAGFILE       =
 15.1415 +
 15.1416 +# If the ALLEXTERNALS tag is set to YES all external classes will be listed
 15.1417 +# in the class index. If set to NO only the inherited external classes
 15.1418 +# will be listed.
 15.1419 +
 15.1420 +ALLEXTERNALS           = NO
 15.1421 +
 15.1422 +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
 15.1423 +# in the modules index. If set to NO, only the current project's groups will
 15.1424 +# be listed.
 15.1425 +
 15.1426 +EXTERNAL_GROUPS        = YES
 15.1427 +
 15.1428 +# The PERL_PATH should be the absolute path and name of the perl script
 15.1429 +# interpreter (i.e. the result of `which perl').
 15.1430 +
 15.1431 +PERL_PATH              = /usr/bin/perl
 15.1432 +
 15.1433 +#---------------------------------------------------------------------------
 15.1434 +# Configuration options related to the dot tool
 15.1435 +#---------------------------------------------------------------------------
 15.1436 +
 15.1437 +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
 15.1438 +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
 15.1439 +# or super classes. Setting the tag to NO turns the diagrams off. Note that
 15.1440 +# this option is superseded by the HAVE_DOT option below. This is only a
 15.1441 +# fallback. It is recommended to install and use dot, since it yields more
 15.1442 +# powerful graphs.
 15.1443 +
 15.1444 +CLASS_DIAGRAMS         = YES
 15.1445 +
 15.1446 +# You can define message sequence charts within doxygen comments using the \msc
 15.1447 +# command. Doxygen will then run the mscgen tool (see
 15.1448 +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
 15.1449 +# documentation. The MSCGEN_PATH tag allows you to specify the directory where
 15.1450 +# the mscgen tool resides. If left empty the tool is assumed to be found in the
 15.1451 +# default search path.
 15.1452 +
 15.1453 +MSCGEN_PATH            =
 15.1454 +
 15.1455 +# If set to YES, the inheritance and collaboration graphs will hide
 15.1456 +# inheritance and usage relations if the target is undocumented
 15.1457 +# or is not a class.
 15.1458 +
 15.1459 +HIDE_UNDOC_RELATIONS   = YES
 15.1460 +
 15.1461 +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
 15.1462 +# available from the path. This tool is part of Graphviz, a graph visualization
 15.1463 +# toolkit from AT&T and Lucent Bell Labs. The other options in this section
 15.1464 +# have no effect if this option is set to NO (the default)
 15.1465 +
 15.1466 +HAVE_DOT               = NO
 15.1467 +
 15.1468 +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
 15.1469 +# allowed to run in parallel. When set to 0 (the default) doxygen will
 15.1470 +# base this on the number of processors available in the system. You can set it
 15.1471 +# explicitly to a value larger than 0 to get control over the balance
 15.1472 +# between CPU load and processing speed.
 15.1473 +
 15.1474 +DOT_NUM_THREADS        = 0
 15.1475 +
 15.1476 +# By default doxygen will write a font called FreeSans.ttf to the output
 15.1477 +# directory and reference it in all dot files that doxygen generates. This
 15.1478 +# font does not include all possible unicode characters however, so when you need
 15.1479 +# these (or just want a differently looking font) you can specify the font name
 15.1480 +# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
 15.1481 +# which can be done by putting it in a standard location or by setting the
 15.1482 +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
 15.1483 +# containing the font.
 15.1484 +
 15.1485 +DOT_FONTNAME           = FreeSans.ttf
 15.1486 +
 15.1487 +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
 15.1488 +# The default size is 10pt.
 15.1489 +
 15.1490 +DOT_FONTSIZE           = 10
 15.1491 +
 15.1492 +# By default doxygen will tell dot to use the output directory to look for the
 15.1493 +# FreeSans.ttf font (which doxygen will put there itself). If you specify a
 15.1494 +# different font using DOT_FONTNAME you can set the path where dot
 15.1495 +# can find it using this tag.
 15.1496 +
 15.1497 +DOT_FONTPATH           =
 15.1498 +
 15.1499 +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
 15.1500 +# will generate a graph for each documented class showing the direct and
 15.1501 +# indirect inheritance relations. Setting this tag to YES will force the
 15.1502 +# the CLASS_DIAGRAMS tag to NO.
 15.1503 +
 15.1504 +CLASS_GRAPH            = YES
 15.1505 +
 15.1506 +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
 15.1507 +# will generate a graph for each documented class showing the direct and
 15.1508 +# indirect implementation dependencies (inheritance, containment, and
 15.1509 +# class references variables) of the class with other documented classes.
 15.1510 +
 15.1511 +COLLABORATION_GRAPH    = YES
 15.1512 +
 15.1513 +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
 15.1514 +# will generate a graph for groups, showing the direct groups dependencies
 15.1515 +
 15.1516 +GROUP_GRAPHS           = YES
 15.1517 +
 15.1518 +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
 15.1519 +# collaboration diagrams in a style similar to the OMG's Unified Modeling
 15.1520 +# Language.
 15.1521 +
 15.1522 +UML_LOOK               = NO
 15.1523 +
 15.1524 +# If set to YES, the inheritance and collaboration graphs will show the
 15.1525 +# relations between templates and their instances.
 15.1526 +
 15.1527 +TEMPLATE_RELATIONS     = NO
 15.1528 +
 15.1529 +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
 15.1530 +# tags are set to YES then doxygen will generate a graph for each documented
 15.1531 +# file showing the direct and indirect include dependencies of the file with
 15.1532 +# other documented files.
 15.1533 +
 15.1534 +INCLUDE_GRAPH          = YES
 15.1535 +
 15.1536 +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
 15.1537 +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
 15.1538 +# documented header file showing the documented files that directly or
 15.1539 +# indirectly include this file.
 15.1540 +
 15.1541 +INCLUDED_BY_GRAPH      = YES
 15.1542 +
 15.1543 +# If the CALL_GRAPH and HAVE_DOT options are set to YES then
 15.1544 +# doxygen will generate a call dependency graph for every global function
 15.1545 +# or class method. Note that enabling this option will significantly increase
 15.1546 +# the time of a run. So in most cases it will be better to enable call graphs
 15.1547 +# for selected functions only using the \callgraph command.
 15.1548 +
 15.1549 +CALL_GRAPH             = NO
 15.1550 +
 15.1551 +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
 15.1552 +# doxygen will generate a caller dependency graph for every global function
 15.1553 +# or class method. Note that enabling this option will significantly increase
 15.1554 +# the time of a run. So in most cases it will be better to enable caller
 15.1555 +# graphs for selected functions only using the \callergraph command.
 15.1556 +
 15.1557 +CALLER_GRAPH           = NO
 15.1558 +
 15.1559 +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
 15.1560 +# will graphical hierarchy of all classes instead of a textual one.
 15.1561 +
 15.1562 +GRAPHICAL_HIERARCHY    = YES
 15.1563 +
 15.1564 +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
 15.1565 +# then doxygen will show the dependencies a directory has on other directories
 15.1566 +# in a graphical way. The dependency relations are determined by the #include
 15.1567 +# relations between the files in the directories.
 15.1568 +
 15.1569 +DIRECTORY_GRAPH        = YES
 15.1570 +
 15.1571 +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
 15.1572 +# generated by dot. Possible values are png, jpg, or gif
 15.1573 +# If left blank png will be used.
 15.1574 +
 15.1575 +DOT_IMAGE_FORMAT       = png
 15.1576 +
 15.1577 +# The tag DOT_PATH can be used to specify the path where the dot tool can be
 15.1578 +# found. If left blank, it is assumed the dot tool can be found in the path.
 15.1579 +
 15.1580 +DOT_PATH               =
 15.1581 +
 15.1582 +# The DOTFILE_DIRS tag can be used to specify one or more directories that
 15.1583 +# contain dot files that are included in the documentation (see the
 15.1584 +# \dotfile command).
 15.1585 +
 15.1586 +DOTFILE_DIRS           =
 15.1587 +
 15.1588 +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
 15.1589 +# nodes that will be shown in the graph. If the number of nodes in a graph
 15.1590 +# becomes larger than this value, doxygen will truncate the graph, which is
 15.1591 +# visualized by representing a node as a red box. Note that doxygen if the
 15.1592 +# number of direct children of the root node in a graph is already larger than
 15.1593 +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
 15.1594 +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
 15.1595 +
 15.1596 +DOT_GRAPH_MAX_NODES    = 50
 15.1597 +
 15.1598 +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
 15.1599 +# graphs generated by dot. A depth value of 3 means that only nodes reachable
 15.1600 +# from the root by following a path via at most 3 edges will be shown. Nodes
 15.1601 +# that lay further from the root node will be omitted. Note that setting this
 15.1602 +# option to 1 or 2 may greatly reduce the computation time needed for large
 15.1603 +# code bases. Also note that the size of a graph can be further restricted by
 15.1604 +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
 15.1605 +
 15.1606 +MAX_DOT_GRAPH_DEPTH    = 0
 15.1607 +
 15.1608 +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
 15.1609 +# background. This is disabled by default, because dot on Windows does not
 15.1610 +# seem to support this out of the box. Warning: Depending on the platform used,
 15.1611 +# enabling this option may lead to badly anti-aliased labels on the edges of
 15.1612 +# a graph (i.e. they become hard to read).
 15.1613 +
 15.1614 +DOT_TRANSPARENT        = NO
 15.1615 +
 15.1616 +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
 15.1617 +# files in one run (i.e. multiple -o and -T options on the command line). This
 15.1618 +# makes dot run faster, but since only newer versions of dot (>1.8.10)
 15.1619 +# support this, this feature is disabled by default.
 15.1620 +
 15.1621 +DOT_MULTI_TARGETS      = YES
 15.1622 +
 15.1623 +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
 15.1624 +# generate a legend page explaining the meaning of the various boxes and
 15.1625 +# arrows in the dot generated graphs.
 15.1626 +
 15.1627 +GENERATE_LEGEND        = YES
 15.1628 +
 15.1629 +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
 15.1630 +# remove the intermediate dot files that are used to generate
 15.1631 +# the various graphs.
 15.1632 +
 15.1633 +DOT_CLEANUP            = YES
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/src/hidapi/hidapi/hidapi.h	Thu Aug 09 16:05:48 2018 -0700
    16.3 @@ -0,0 +1,398 @@
    16.4 +/*******************************************************
    16.5 + HIDAPI - Multi-Platform library for
    16.6 + communication with HID devices.
    16.7 +
    16.8 + Alan Ott
    16.9 + Signal 11 Software
   16.10 +
   16.11 + 8/22/2009
   16.12 +
   16.13 + Copyright 2009, All Rights Reserved.
   16.14 +
   16.15 + At the discretion of the user of this library,
   16.16 + this software may be licensed under the terms of the
   16.17 + GNU General Public License v3, a BSD-Style license, or the
   16.18 + original HIDAPI license as outlined in the LICENSE.txt,
   16.19 + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
   16.20 + files located at the root of the source distribution.
   16.21 + These files may also be found in the public source
   16.22 + code repository located at:
   16.23 +        http://github.com/signal11/hidapi .
   16.24 +********************************************************/
   16.25 +
   16.26 +/** @file
   16.27 + * @defgroup API hidapi API
   16.28 + */
   16.29 +
   16.30 +#ifndef HIDAPI_H__
   16.31 +#define HIDAPI_H__
   16.32 +
   16.33 +#include <wchar.h>
   16.34 +
   16.35 +#if defined(_WIN32) && !defined(NAMESPACE)
   16.36 +      #define HID_API_EXPORT __declspec(dllexport)
   16.37 +      #define HID_API_CALL
   16.38 +#else
   16.39 +      #define HID_API_EXPORT /**< API export macro */
   16.40 +      #define HID_API_CALL /**< API call macro */
   16.41 +#endif
   16.42 +
   16.43 +#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/
   16.44 +
   16.45 +#if defined(__cplusplus) && !defined(NAMESPACE)
   16.46 +extern "C" {
   16.47 +#endif
   16.48 +#ifdef NAMESPACE
   16.49 +namespace NAMESPACE {
   16.50 +#endif
   16.51 +
   16.52 +		struct hid_device_;
   16.53 +		typedef struct hid_device_ hid_device; /**< opaque hidapi structure */
   16.54 +
   16.55 +		/** hidapi info structure */
   16.56 +		struct hid_device_info {
   16.57 +			/** Platform-specific device path */
   16.58 +			char *path;
   16.59 +			/** Device Vendor ID */
   16.60 +			unsigned short vendor_id;
   16.61 +			/** Device Product ID */
   16.62 +			unsigned short product_id;
   16.63 +			/** Serial Number */
   16.64 +			wchar_t *serial_number;
   16.65 +			/** Device Release Number in binary-coded decimal,
   16.66 +			    also known as Device Version Number */
   16.67 +			unsigned short release_number;
   16.68 +			/** Manufacturer String */
   16.69 +			wchar_t *manufacturer_string;
   16.70 +			/** Product string */
   16.71 +			wchar_t *product_string;
   16.72 +			/** Usage Page for this Device/Interface
   16.73 +			    (Windows/Mac only). */
   16.74 +			unsigned short usage_page;
   16.75 +			/** Usage for this Device/Interface
   16.76 +			    (Windows/Mac only).*/
   16.77 +			unsigned short usage;
   16.78 +			/** The USB interface which this logical device
   16.79 +			    represents. Valid on both Linux implementations
   16.80 +			    in all cases, and valid on the Windows implementation
   16.81 +			    only if the device contains more than one interface. */
   16.82 +			int interface_number;
   16.83 +
   16.84 +			/** Pointer to the next device */
   16.85 +			struct hid_device_info *next;
   16.86 +		};
   16.87 +
   16.88 +
   16.89 +		/** @brief Initialize the HIDAPI library.
   16.90 +
   16.91 +			This function initializes the HIDAPI library. Calling it is not
   16.92 +			strictly necessary, as it will be called automatically by
   16.93 +			hid_enumerate() and any of the hid_open_*() functions if it is
   16.94 +			needed.  This function should be called at the beginning of
   16.95 +			execution however, if there is a chance of HIDAPI handles
   16.96 +			being opened by different threads simultaneously.
   16.97 +			
   16.98 +			@ingroup API
   16.99 +
  16.100 +			@returns
  16.101 +				This function returns 0 on success and -1 on error.
  16.102 +		*/
  16.103 +		int HID_API_EXPORT HID_API_CALL hid_init(void);
  16.104 +
  16.105 +		/** @brief Finalize the HIDAPI library.
  16.106 +
  16.107 +			This function frees all of the static data associated with
  16.108 +			HIDAPI. It should be called at the end of execution to avoid
  16.109 +			memory leaks.
  16.110 +
  16.111 +			@ingroup API
  16.112 +
  16.113 +		    @returns
  16.114 +				This function returns 0 on success and -1 on error.
  16.115 +		*/
  16.116 +		int HID_API_EXPORT HID_API_CALL hid_exit(void);
  16.117 +
  16.118 +		/** @brief Enumerate the HID Devices.
  16.119 +
  16.120 +			This function returns a linked list of all the HID devices
  16.121 +			attached to the system which match vendor_id and product_id.
  16.122 +			If @p vendor_id is set to 0 then any vendor matches.
  16.123 +			If @p product_id is set to 0 then any product matches.
  16.124 +			If @p vendor_id and @p product_id are both set to 0, then
  16.125 +			all HID devices will be returned.
  16.126 +
  16.127 +			@ingroup API
  16.128 +			@param vendor_id The Vendor ID (VID) of the types of device
  16.129 +				to open.
  16.130 +			@param product_id The Product ID (PID) of the types of
  16.131 +				device to open.
  16.132 +
  16.133 +		    @returns
  16.134 +		    	This function returns a pointer to a linked list of type
  16.135 +		    	struct #hid_device, containing information about the HID devices
  16.136 +		    	attached to the system, or NULL in the case of failure. Free
  16.137 +		    	this linked list by calling hid_free_enumeration().
  16.138 +		*/
  16.139 +		struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id);
  16.140 +
  16.141 +		/** @brief Free an enumeration Linked List
  16.142 +
  16.143 +		    This function frees a linked list created by hid_enumerate().
  16.144 +
  16.145 +			@ingroup API
  16.146 +		    @param devs Pointer to a list of struct_device returned from
  16.147 +		    	      hid_enumerate().
  16.148 +		*/
  16.149 +		void  HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs);
  16.150 +
  16.151 +		/** @brief Open a HID device using a Vendor ID (VID), Product ID
  16.152 +			(PID) and optionally a serial number.
  16.153 +
  16.154 +			If @p serial_number is NULL, the first device with the
  16.155 +			specified VID and PID is opened.
  16.156 +
  16.157 +			@ingroup API
  16.158 +			@param vendor_id The Vendor ID (VID) of the device to open.
  16.159 +			@param product_id The Product ID (PID) of the device to open.
  16.160 +			@param serial_number The Serial Number of the device to open
  16.161 +				               (Optionally NULL).
  16.162 +
  16.163 +			@returns
  16.164 +				This function returns a pointer to a #hid_device object on
  16.165 +				success or NULL on failure.
  16.166 +		*/
  16.167 +		HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number);
  16.168 +
  16.169 +		/** @brief Open a HID device by its path name.
  16.170 +
  16.171 +			The path name be determined by calling hid_enumerate(), or a
  16.172 +			platform-specific path name can be used (eg: /dev/hidraw0 on
  16.173 +			Linux).
  16.174 +
  16.175 +			@ingroup API
  16.176 +		    @param path The path name of the device to open
  16.177 +
  16.178 +			@returns
  16.179 +				This function returns a pointer to a #hid_device object on
  16.180 +				success or NULL on failure.
  16.181 +		*/
  16.182 +		HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path, int bExclusive /* = false */);
  16.183 +
  16.184 +		/** @brief Write an Output report to a HID device.
  16.185 +
  16.186 +			The first byte of @p data[] must contain the Report ID. For
  16.187 +			devices which only support a single report, this must be set
  16.188 +			to 0x0. The remaining bytes contain the report data. Since
  16.189 +			the Report ID is mandatory, calls to hid_write() will always
  16.190 +			contain one more byte than the report contains. For example,
  16.191 +			if a hid report is 16 bytes long, 17 bytes must be passed to
  16.192 +			hid_write(), the Report ID (or 0x0, for devices with a
  16.193 +			single report), followed by the report data (16 bytes). In
  16.194 +			this example, the length passed in would be 17.
  16.195 +
  16.196 +			hid_write() will send the data on the first OUT endpoint, if
  16.197 +			one exists. If it does not, it will send the data through
  16.198 +			the Control Endpoint (Endpoint 0).
  16.199 +
  16.200 +			@ingroup API
  16.201 +			@param device A device handle returned from hid_open().
  16.202 +			@param data The data to send, including the report number as
  16.203 +				the first byte.
  16.204 +			@param length The length in bytes of the data to send.
  16.205 +
  16.206 +			@returns
  16.207 +				This function returns the actual number of bytes written and
  16.208 +				-1 on error.
  16.209 +		*/
  16.210 +		int  HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length);
  16.211 +
  16.212 +		/** @brief Read an Input report from a HID device with timeout.
  16.213 +
  16.214 +			Input reports are returned
  16.215 +			to the host through the INTERRUPT IN endpoint. The first byte will
  16.216 +			contain the Report number if the device uses numbered reports.
  16.217 +
  16.218 +			@ingroup API
  16.219 +			@param device A device handle returned from hid_open().
  16.220 +			@param data A buffer to put the read data into.
  16.221 +			@param length The number of bytes to read. For devices with
  16.222 +				multiple reports, make sure to read an extra byte for
  16.223 +				the report number.
  16.224 +			@param milliseconds timeout in milliseconds or -1 for blocking wait.
  16.225 +
  16.226 +			@returns
  16.227 +				This function returns the actual number of bytes read and
  16.228 +				-1 on error. If no packet was available to be read within
  16.229 +				the timeout period, this function returns 0.
  16.230 +		*/
  16.231 +		int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds);
  16.232 +
  16.233 +		/** @brief Read an Input report from a HID device.
  16.234 +
  16.235 +			Input reports are returned
  16.236 +		    to the host through the INTERRUPT IN endpoint. The first byte will
  16.237 +			contain the Report number if the device uses numbered reports.
  16.238 +
  16.239 +			@ingroup API
  16.240 +			@param device A device handle returned from hid_open().
  16.241 +			@param data A buffer to put the read data into.
  16.242 +			@param length The number of bytes to read. For devices with
  16.243 +				multiple reports, make sure to read an extra byte for
  16.244 +				the report number.
  16.245 +
  16.246 +			@returns
  16.247 +				This function returns the actual number of bytes read and
  16.248 +				-1 on error. If no packet was available to be read and
  16.249 +				the handle is in non-blocking mode, this function returns 0.
  16.250 +		*/
  16.251 +		int  HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length);
  16.252 +
  16.253 +		/** @brief Set the device handle to be non-blocking.
  16.254 +
  16.255 +			In non-blocking mode calls to hid_read() will return
  16.256 +			immediately with a value of 0 if there is no data to be
  16.257 +			read. In blocking mode, hid_read() will wait (block) until
  16.258 +			there is data to read before returning.
  16.259 +
  16.260 +			Nonblocking can be turned on and off at any time.
  16.261 +
  16.262 +			@ingroup API
  16.263 +			@param device A device handle returned from hid_open().
  16.264 +			@param nonblock enable or not the nonblocking reads
  16.265 +			 - 1 to enable nonblocking
  16.266 +			 - 0 to disable nonblocking.
  16.267 +
  16.268 +			@returns
  16.269 +				This function returns 0 on success and -1 on error.
  16.270 +		*/
  16.271 +		int  HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock);
  16.272 +
  16.273 +		/** @brief Send a Feature report to the device.
  16.274 +
  16.275 +			Feature reports are sent over the Control endpoint as a
  16.276 +			Set_Report transfer.  The first byte of @p data[] must
  16.277 +			contain the Report ID. For devices which only support a
  16.278 +			single report, this must be set to 0x0. The remaining bytes
  16.279 +			contain the report data. Since the Report ID is mandatory,
  16.280 +			calls to hid_send_feature_report() will always contain one
  16.281 +			more byte than the report contains. For example, if a hid
  16.282 +			report is 16 bytes long, 17 bytes must be passed to
  16.283 +			hid_send_feature_report(): the Report ID (or 0x0, for
  16.284 +			devices which do not use numbered reports), followed by the
  16.285 +			report data (16 bytes). In this example, the length passed
  16.286 +			in would be 17.
  16.287 +
  16.288 +			@ingroup API
  16.289 +			@param device A device handle returned from hid_open().
  16.290 +			@param data The data to send, including the report number as
  16.291 +				the first byte.
  16.292 +			@param length The length in bytes of the data to send, including
  16.293 +				the report number.
  16.294 +
  16.295 +			@returns
  16.296 +				This function returns the actual number of bytes written and
  16.297 +				-1 on error.
  16.298 +		*/
  16.299 +		int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length);
  16.300 +
  16.301 +		/** @brief Get a feature report from a HID device.
  16.302 +
  16.303 +			Set the first byte of @p data[] to the Report ID of the
  16.304 +			report to be read.  Make sure to allow space for this
  16.305 +			extra byte in @p data[]. Upon return, the first byte will
  16.306 +			still contain the Report ID, and the report data will
  16.307 +			start in data[1].
  16.308 +
  16.309 +			@ingroup API
  16.310 +			@param device A device handle returned from hid_open().
  16.311 +			@param data A buffer to put the read data into, including
  16.312 +				the Report ID. Set the first byte of @p data[] to the
  16.313 +				Report ID of the report to be read, or set it to zero
  16.314 +				if your device does not use numbered reports.
  16.315 +			@param length The number of bytes to read, including an
  16.316 +				extra byte for the report ID. The buffer can be longer
  16.317 +				than the actual report.
  16.318 +
  16.319 +			@returns
  16.320 +				This function returns the number of bytes read plus
  16.321 +				one for the report ID (which is still in the first
  16.322 +				byte), or -1 on error.
  16.323 +		*/
  16.324 +		int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length);
  16.325 +
  16.326 +		/** @brief Close a HID device.
  16.327 +
  16.328 +			@ingroup API
  16.329 +			@param device A device handle returned from hid_open().
  16.330 +		*/
  16.331 +		void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device);
  16.332 +
  16.333 +		/** @brief Get The Manufacturer String from a HID device.
  16.334 +
  16.335 +			@ingroup API
  16.336 +			@param device A device handle returned from hid_open().
  16.337 +			@param string A wide string buffer to put the data into.
  16.338 +			@param maxlen The length of the buffer in multiples of wchar_t.
  16.339 +
  16.340 +			@returns
  16.341 +				This function returns 0 on success and -1 on error.
  16.342 +		*/
  16.343 +		int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen);
  16.344 +
  16.345 +		/** @brief Get The Product String from a HID device.
  16.346 +
  16.347 +			@ingroup API
  16.348 +			@param device A device handle returned from hid_open().
  16.349 +			@param string A wide string buffer to put the data into.
  16.350 +			@param maxlen The length of the buffer in multiples of wchar_t.
  16.351 +
  16.352 +			@returns
  16.353 +				This function returns 0 on success and -1 on error.
  16.354 +		*/
  16.355 +		int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen);
  16.356 +
  16.357 +		/** @brief Get The Serial Number String from a HID device.
  16.358 +
  16.359 +			@ingroup API
  16.360 +			@param device A device handle returned from hid_open().
  16.361 +			@param string A wide string buffer to put the data into.
  16.362 +			@param maxlen The length of the buffer in multiples of wchar_t.
  16.363 +
  16.364 +			@returns
  16.365 +				This function returns 0 on success and -1 on error.
  16.366 +		*/
  16.367 +		int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen);
  16.368 +
  16.369 +		/** @brief Get a string from a HID device, based on its string index.
  16.370 +
  16.371 +			@ingroup API
  16.372 +			@param device A device handle returned from hid_open().
  16.373 +			@param string_index The index of the string to get.
  16.374 +			@param string A wide string buffer to put the data into.
  16.375 +			@param maxlen The length of the buffer in multiples of wchar_t.
  16.376 +
  16.377 +			@returns
  16.378 +				This function returns 0 on success and -1 on error.
  16.379 +		*/
  16.380 +		int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen);
  16.381 +
  16.382 +		/** @brief Get a string describing the last error which occurred.
  16.383 +
  16.384 +			@ingroup API
  16.385 +			@param device A device handle returned from hid_open().
  16.386 +
  16.387 +			@returns
  16.388 +				This function returns a string containing the last error
  16.389 +				which occurred or NULL if none has occurred.
  16.390 +		*/
  16.391 +		HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device);
  16.392 +
  16.393 +#if defined(__cplusplus) && !defined(NAMESPACE)
  16.394 +}
  16.395 +#endif
  16.396 +#ifdef NAMESPACE
  16.397 +}
  16.398 +#endif
  16.399 +
  16.400 +#endif
  16.401 +
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/src/hidapi/hidtest/Makefile.am	Thu Aug 09 16:05:48 2018 -0700
    17.3 @@ -0,0 +1,20 @@
    17.4 +AM_CPPFLAGS = -I$(top_srcdir)/hidapi/
    17.5 +
    17.6 +## Linux
    17.7 +if OS_LINUX
    17.8 +noinst_PROGRAMS = hidtest-libusb hidtest-hidraw
    17.9 +
   17.10 +hidtest_hidraw_SOURCES = hidtest.cpp
   17.11 +hidtest_hidraw_LDADD = $(top_builddir)/linux/libhidapi-hidraw.la
   17.12 +
   17.13 +hidtest_libusb_SOURCES = hidtest.cpp
   17.14 +hidtest_libusb_LDADD = $(top_builddir)/libusb/libhidapi-libusb.la
   17.15 +else
   17.16 +
   17.17 +# Other OS's
   17.18 +noinst_PROGRAMS = hidtest
   17.19 +
   17.20 +hidtest_SOURCES = hidtest.cpp
   17.21 +hidtest_LDADD = $(top_builddir)/$(backend)/libhidapi.la
   17.22 +
   17.23 +endif
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/src/hidapi/hidtest/hidtest.cpp	Thu Aug 09 16:05:48 2018 -0700
    18.3 @@ -0,0 +1,194 @@
    18.4 +/*******************************************************
    18.5 + Windows HID simplification
    18.6 +
    18.7 + Alan Ott
    18.8 + Signal 11 Software
    18.9 +
   18.10 + 8/22/2009
   18.11 +
   18.12 + Copyright 2009
   18.13 + 
   18.14 + This contents of this file may be used by anyone
   18.15 + for any reason without any conditions and may be
   18.16 + used as a starting point for your own applications
   18.17 + which use HIDAPI.
   18.18 +********************************************************/
   18.19 +
   18.20 +#include <stdio.h>
   18.21 +#include <wchar.h>
   18.22 +#include <string.h>
   18.23 +#include <stdlib.h>
   18.24 +#include "hidapi.h"
   18.25 +
   18.26 +// Headers needed for sleeping.
   18.27 +#ifdef _WIN32
   18.28 +	#include <windows.h>
   18.29 +#else
   18.30 +	#include <unistd.h>
   18.31 +#endif
   18.32 +
   18.33 +int main(int argc, char* argv[])
   18.34 +{
   18.35 +	int res;
   18.36 +	unsigned char buf[256];
   18.37 +	#define MAX_STR 255
   18.38 +	wchar_t wstr[MAX_STR];
   18.39 +	hid_device *handle;
   18.40 +	int i;
   18.41 +
   18.42 +#ifdef WIN32
   18.43 +	UNREFERENCED_PARAMETER(argc);
   18.44 +	UNREFERENCED_PARAMETER(argv);
   18.45 +#endif
   18.46 +
   18.47 +	struct hid_device_info *devs, *cur_dev;
   18.48 +	
   18.49 +	if (hid_init())
   18.50 +		return -1;
   18.51 +
   18.52 +	devs = hid_enumerate(0x0, 0x0);
   18.53 +	cur_dev = devs;	
   18.54 +	while (cur_dev) {
   18.55 +		printf("Device Found\n  type: %04hx %04hx\n  path: %s\n  serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
   18.56 +		printf("\n");
   18.57 +		printf("  Manufacturer: %ls\n", cur_dev->manufacturer_string);
   18.58 +		printf("  Product:      %ls\n", cur_dev->product_string);
   18.59 +		printf("  Release:      %hx\n", cur_dev->release_number);
   18.60 +		printf("  Interface:    %d\n",  cur_dev->interface_number);
   18.61 +		printf("\n");
   18.62 +		cur_dev = cur_dev->next;
   18.63 +	}
   18.64 +	hid_free_enumeration(devs);
   18.65 +
   18.66 +	// Set up the command buffer.
   18.67 +	memset(buf,0x00,sizeof(buf));
   18.68 +	buf[0] = 0x01;
   18.69 +	buf[1] = 0x81;
   18.70 +	
   18.71 +
   18.72 +	// Open the device using the VID, PID,
   18.73 +	// and optionally the Serial number.
   18.74 +	////handle = hid_open(0x4d8, 0x3f, L"12345");
   18.75 +	handle = hid_open(0x4d8, 0x3f, NULL);
   18.76 +	if (!handle) {
   18.77 +		printf("unable to open device\n");
   18.78 + 		return 1;
   18.79 +	}
   18.80 +
   18.81 +	// Read the Manufacturer String
   18.82 +	wstr[0] = 0x0000;
   18.83 +	res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
   18.84 +	if (res < 0)
   18.85 +		printf("Unable to read manufacturer string\n");
   18.86 +	printf("Manufacturer String: %ls\n", wstr);
   18.87 +
   18.88 +	// Read the Product String
   18.89 +	wstr[0] = 0x0000;
   18.90 +	res = hid_get_product_string(handle, wstr, MAX_STR);
   18.91 +	if (res < 0)
   18.92 +		printf("Unable to read product string\n");
   18.93 +	printf("Product String: %ls\n", wstr);
   18.94 +
   18.95 +	// Read the Serial Number String
   18.96 +	wstr[0] = 0x0000;
   18.97 +	res = hid_get_serial_number_string(handle, wstr, MAX_STR);
   18.98 +	if (res < 0)
   18.99 +		printf("Unable to read serial number string\n");
  18.100 +	printf("Serial Number String: (%d) %ls", wstr[0], wstr);
  18.101 +	printf("\n");
  18.102 +
  18.103 +	// Read Indexed String 1
  18.104 +	wstr[0] = 0x0000;
  18.105 +	res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
  18.106 +	if (res < 0)
  18.107 +		printf("Unable to read indexed string 1\n");
  18.108 +	printf("Indexed String 1: %ls\n", wstr);
  18.109 +
  18.110 +	// Set the hid_read() function to be non-blocking.
  18.111 +	hid_set_nonblocking(handle, 1);
  18.112 +	
  18.113 +	// Try to read from the device. There shoud be no
  18.114 +	// data here, but execution should not block.
  18.115 +	res = hid_read(handle, buf, 17);
  18.116 +
  18.117 +	// Send a Feature Report to the device
  18.118 +	buf[0] = 0x2;
  18.119 +	buf[1] = 0xa0;
  18.120 +	buf[2] = 0x0a;
  18.121 +	buf[3] = 0x00;
  18.122 +	buf[4] = 0x00;
  18.123 +	res = hid_send_feature_report(handle, buf, 17);
  18.124 +	if (res < 0) {
  18.125 +		printf("Unable to send a feature report.\n");
  18.126 +	}
  18.127 +
  18.128 +	memset(buf,0,sizeof(buf));
  18.129 +
  18.130 +	// Read a Feature Report from the device
  18.131 +	buf[0] = 0x2;
  18.132 +	res = hid_get_feature_report(handle, buf, sizeof(buf));
  18.133 +	if (res < 0) {
  18.134 +		printf("Unable to get a feature report.\n");
  18.135 +		printf("%ls", hid_error(handle));
  18.136 +	}
  18.137 +	else {
  18.138 +		// Print out the returned buffer.
  18.139 +		printf("Feature Report\n   ");
  18.140 +		for (i = 0; i < res; i++)
  18.141 +			printf("%02hhx ", buf[i]);
  18.142 +		printf("\n");
  18.143 +	}
  18.144 +
  18.145 +	memset(buf,0,sizeof(buf));
  18.146 +
  18.147 +	// Toggle LED (cmd 0x80). The first byte is the report number (0x1).
  18.148 +	buf[0] = 0x1;
  18.149 +	buf[1] = 0x80;
  18.150 +	res = hid_write(handle, buf, 17);
  18.151 +	if (res < 0) {
  18.152 +		printf("Unable to write()\n");
  18.153 +		printf("Error: %ls\n", hid_error(handle));
  18.154 +	}
  18.155 +	
  18.156 +
  18.157 +	// Request state (cmd 0x81). The first byte is the report number (0x1).
  18.158 +	buf[0] = 0x1;
  18.159 +	buf[1] = 0x81;
  18.160 +	hid_write(handle, buf, 17);
  18.161 +	if (res < 0)
  18.162 +		printf("Unable to write() (2)\n");
  18.163 +
  18.164 +	// Read requested state. hid_read() has been set to be
  18.165 +	// non-blocking by the call to hid_set_nonblocking() above.
  18.166 +	// This loop demonstrates the non-blocking nature of hid_read().
  18.167 +	res = 0;
  18.168 +	while (res == 0) {
  18.169 +		res = hid_read(handle, buf, sizeof(buf));
  18.170 +		if (res == 0)
  18.171 +			printf("waiting...\n");
  18.172 +		if (res < 0)
  18.173 +			printf("Unable to read()\n");
  18.174 +		#ifdef WIN32
  18.175 +		Sleep(500);
  18.176 +		#else
  18.177 +		usleep(500*1000);
  18.178 +		#endif
  18.179 +	}
  18.180 +
  18.181 +	printf("Data read:\n   ");
  18.182 +	// Print out the returned buffer.
  18.183 +	for (i = 0; i < res; i++)
  18.184 +		printf("%02hhx ", buf[i]);
  18.185 +	printf("\n");
  18.186 +
  18.187 +	hid_close(handle);
  18.188 +
  18.189 +	/* Free static HIDAPI objects. */
  18.190 +	hid_exit();
  18.191 +
  18.192 +#ifdef WIN32
  18.193 +	system("pause");
  18.194 +#endif
  18.195 +
  18.196 +	return 0;
  18.197 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/src/hidapi/ios/Makefile-manual	Thu Aug 09 16:05:48 2018 -0700
    19.3 @@ -0,0 +1,32 @@
    19.4 +###########################################
    19.5 +# Simple Makefile for HIDAPI test program
    19.6 +#
    19.7 +# Alan Ott
    19.8 +# Signal 11 Software
    19.9 +# 2010-07-03
   19.10 +###########################################
   19.11 +
   19.12 +all: hidtest
   19.13 +
   19.14 +CC=gcc
   19.15 +CXX=g++
   19.16 +COBJS=hid.o
   19.17 +CPPOBJS=../hidtest/hidtest.o
   19.18 +OBJS=$(COBJS) $(CPPOBJS)
   19.19 +CFLAGS+=-I../hidapi -Wall -g -c 
   19.20 +LIBS=-framework CoreBluetooth -framework CoreFoundation
   19.21 +
   19.22 +
   19.23 +hidtest: $(OBJS)
   19.24 +	g++ -Wall -g $^ $(LIBS) -o hidtest
   19.25 +
   19.26 +$(COBJS): %.o: %.c
   19.27 +	$(CC) $(CFLAGS) $< -o $@
   19.28 +
   19.29 +$(CPPOBJS): %.o: %.cpp
   19.30 +	$(CXX) $(CFLAGS) $< -o $@
   19.31 +
   19.32 +clean:
   19.33 +	rm -f *.o hidtest $(CPPOBJS)
   19.34 +
   19.35 +.PHONY: clean
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/src/hidapi/ios/Makefile.am	Thu Aug 09 16:05:48 2018 -0700
    20.3 @@ -0,0 +1,9 @@
    20.4 +lib_LTLIBRARIES = libhidapi.la
    20.5 +libhidapi_la_SOURCES = hid.m
    20.6 +libhidapi_la_LDFLAGS = $(LTLDFLAGS)
    20.7 +AM_CPPFLAGS = -I$(top_srcdir)/hidapi/
    20.8 +
    20.9 +hdrdir = $(includedir)/hidapi
   20.10 +hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h
   20.11 +
   20.12 +EXTRA_DIST = Makefile-manual
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/src/hidapi/ios/hid.mm	Thu Aug 09 16:05:48 2018 -0700
    21.3 @@ -0,0 +1,883 @@
    21.4 +//======== Copyright (c) 2017 Valve Corporation, All rights reserved. =========
    21.5 +//
    21.6 +// Purpose: HID device abstraction temporary stub
    21.7 +//
    21.8 +//=============================================================================
    21.9 +
   21.10 +#include <CoreBluetooth/CoreBluetooth.h>
   21.11 +#include <QuartzCore/QuartzCore.h>
   21.12 +#import <UIKit/UIKit.h>
   21.13 +#import <mach/mach_time.h>
   21.14 +#include <pthread.h>
   21.15 +#include <sys/time.h>
   21.16 +#include <unistd.h>
   21.17 +#include "../hidapi/hidapi.h"
   21.18 +
   21.19 +#define VALVE_USB_VID       0x28DE
   21.20 +#define D0G_BLE2_PID        0x1106
   21.21 +
   21.22 +typedef uint32_t uint32;
   21.23 +typedef uint64_t uint64;
   21.24 +
   21.25 +// enables detailed NSLog logging of feature reports
   21.26 +#define FEATURE_REPORT_LOGGING	0
   21.27 +
   21.28 +#define REPORT_SEGMENT_DATA_FLAG	0x80
   21.29 +#define REPORT_SEGMENT_LAST_FLAG	0x40
   21.30 +
   21.31 +#define VALVE_SERVICE		@"100F6C32-1735-4313-B402-38567131E5F3"
   21.32 +
   21.33 +// (READ/NOTIFICATIONS)
   21.34 +#define VALVE_INPUT_CHAR	@"100F6C33-1735-4313-B402-38567131E5F3"
   21.35 +
   21.36 +//  (READ/WRITE)
   21.37 +#define VALVE_REPORT_CHAR	@"100F6C34-1735-4313-B402-38567131E5F3"
   21.38 +
   21.39 +// TODO: create CBUUID's in __attribute__((constructor)) rather than doing [CBUUID UUIDWithString:...] everywhere
   21.40 +
   21.41 +#pragma pack(push,1)
   21.42 +struct bluetoothSegment {
   21.43 +	uint8_t		segmentHeader;
   21.44 +	uint8_t		featureReportMessageID;
   21.45 +	uint8_t		length;
   21.46 +	uint8_t		settingIdentifier;
   21.47 +	union {
   21.48 +		uint16_t	usPayload;
   21.49 +		uint32_t	uPayload;
   21.50 +		uint64_t	ulPayload;
   21.51 +		uint8_t		ucPayload[15];
   21.52 +	};
   21.53 +	
   21.54 +	size_t size() { return length + 3; }
   21.55 +};
   21.56 +
   21.57 +struct hidFeatureReport {
   21.58 +	uint8_t		id;
   21.59 +	union {
   21.60 +		bluetoothSegment segment;
   21.61 +		struct {
   21.62 +			uint8_t		segmentHeader;
   21.63 +			uint8_t		featureReportMessageID;
   21.64 +			uint8_t		length;
   21.65 +			uint8_t		settingIdentifier;
   21.66 +			union {
   21.67 +				uint16_t	usPayload;
   21.68 +				uint32_t	uPayload;
   21.69 +				uint64_t	ulPayload;
   21.70 +				uint8_t		ucPayload[15];
   21.71 +			};
   21.72 +		};
   21.73 +	};
   21.74 +};
   21.75 +#pragma pack(pop)
   21.76 +
   21.77 +template <typename T, size_t cbElem, size_t nElem>
   21.78 +struct RingBuffer {
   21.79 +	int _first, _last;
   21.80 +	uint8_t _data[ ( nElem * cbElem ) ];
   21.81 +	pthread_mutex_t accessLock;
   21.82 +	
   21.83 +	RingBuffer() { _first = -1; _last = 0; pthread_mutex_init( &accessLock, 0 ); }
   21.84 +	
   21.85 +	bool write( const T *src )
   21.86 +	{
   21.87 +		pthread_mutex_lock( &accessLock );
   21.88 +		memcpy( &_data[ _last ], src, cbElem );
   21.89 +		if ( _first == -1 )
   21.90 +		{
   21.91 +			_first = _last;
   21.92 +		}
   21.93 +		_last = ( _last + cbElem ) % (nElem * cbElem);
   21.94 +		if ( _last == _first )
   21.95 +		{
   21.96 +			_first = ( _first + cbElem ) % (nElem * cbElem);
   21.97 +			pthread_mutex_unlock( &accessLock );
   21.98 +			return false;
   21.99 +		}
  21.100 +		pthread_mutex_unlock( &accessLock );
  21.101 +		return true;
  21.102 +	}
  21.103 +	
  21.104 +	bool read( T *dst )
  21.105 +	{
  21.106 +		pthread_mutex_lock( &accessLock );
  21.107 +		if ( _first == -1 )
  21.108 +		{
  21.109 +			pthread_mutex_unlock( &accessLock );
  21.110 +			return false;
  21.111 +		}
  21.112 +		memcpy( dst, &_data[ _first ], cbElem );
  21.113 +		_first = ( _first + cbElem ) % (nElem * cbElem);
  21.114 +		if ( _first == _last )
  21.115 +		{
  21.116 +			_first = -1;
  21.117 +		}
  21.118 +		pthread_mutex_unlock( &accessLock );
  21.119 +		return true;
  21.120 +	}
  21.121 +	
  21.122 +};
  21.123 +
  21.124 +
  21.125 +#pragma mark HIDBLEDevice Definition
  21.126 +
  21.127 +enum BLEDeviceWaitState
  21.128 +{
  21.129 +	None,
  21.130 +	Waiting,
  21.131 +	Complete,
  21.132 +	Error
  21.133 +};
  21.134 +
  21.135 +@interface HIDBLEDevice : NSObject <CBPeripheralDelegate>
  21.136 +{
  21.137 +	RingBuffer<uint8_t, 19, 4096> _inputReports;
  21.138 +	uint8_t		_featureReport[20];
  21.139 +	BLEDeviceWaitState	_waitStateForReadFeatureReport;
  21.140 +	BLEDeviceWaitState	_waitStateForWriteFeatureReport;
  21.141 +}
  21.142 +
  21.143 +@property (nonatomic, readwrite) bool connected;
  21.144 +@property (nonatomic, readwrite) bool ready;
  21.145 +
  21.146 +@property (nonatomic, strong) CBPeripheral     *bleSteamController;
  21.147 +@property (nonatomic, strong) CBCharacteristic *bleCharacteristicInput;
  21.148 +@property (nonatomic, strong) CBCharacteristic *bleCharacteristicReport;
  21.149 +
  21.150 +- (id)initWithPeripheral:(CBPeripheral *)peripheral;
  21.151 +
  21.152 +@end
  21.153 +
  21.154 +
  21.155 +@interface HIDBLEManager : NSObject <CBCentralManagerDelegate>
  21.156 +
  21.157 +@property (nonatomic) int nPendingScans;
  21.158 +@property (nonatomic) int nPendingPairs;
  21.159 +@property (nonatomic, strong) CBCentralManager *centralManager;
  21.160 +@property (nonatomic, strong) NSMapTable<CBPeripheral *, HIDBLEDevice *> *deviceMap;
  21.161 +@property (nonatomic, retain) dispatch_queue_t bleSerialQueue;
  21.162 +
  21.163 ++ (instancetype)sharedInstance;
  21.164 +- (void)startScan:(int)duration;
  21.165 +- (void)stopScan;
  21.166 +- (int)updateConnectedSteamControllers:(BOOL) bForce;
  21.167 +- (void)appWillResignActiveNotification:(NSNotification *)note;
  21.168 +- (void)appDidBecomeActiveNotification:(NSNotification *)note;
  21.169 +
  21.170 +@end
  21.171 +
  21.172 +
  21.173 +// singleton class - access using HIDBLEManager.sharedInstance
  21.174 +@implementation HIDBLEManager
  21.175 +
  21.176 ++ (instancetype)sharedInstance
  21.177 +{
  21.178 +	static HIDBLEManager *sharedInstance = nil;
  21.179 +	static dispatch_once_t onceToken;
  21.180 +	dispatch_once(&onceToken, ^{
  21.181 +		sharedInstance = [HIDBLEManager new];
  21.182 +		sharedInstance.nPendingScans = 0;
  21.183 +		sharedInstance.nPendingPairs = 0;
  21.184 +		
  21.185 +		[[NSNotificationCenter defaultCenter] addObserver:sharedInstance selector:@selector(appWillResignActiveNotification:) name: UIApplicationWillResignActiveNotification object:nil];
  21.186 +		[[NSNotificationCenter defaultCenter] addObserver:sharedInstance selector:@selector(appDidBecomeActiveNotification:) name:UIApplicationDidBecomeActiveNotification object:nil];
  21.187 +
  21.188 +		// receive reports on a high-priority serial-queue. optionally put writes on the serial queue to avoid logical
  21.189 +		// race conditions talking to the controller from multiple threads, although BLE fragmentation/assembly means
  21.190 +		// that we can still screw this up.
  21.191 +		// most importantly we need to consume reports at a high priority to avoid the OS thinking we aren't really
  21.192 +		// listening to the BLE device, as iOS on slower devices may stop delivery of packets to the app WITHOUT ACTUALLY
  21.193 +		// DISCONNECTING FROM THE DEVICE if we don't react quickly enough to their delivery.
  21.194 +		// see also the error-handling states in the peripheral delegate to re-open the device if it gets closed
  21.195 +		sharedInstance.bleSerialQueue = dispatch_queue_create( "com.valvesoftware.steamcontroller.ble", DISPATCH_QUEUE_SERIAL );
  21.196 +		dispatch_set_target_queue( sharedInstance.bleSerialQueue, dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0 ) );
  21.197 +
  21.198 +		// creating a CBCentralManager will always trigger a future centralManagerDidUpdateState:
  21.199 +		// where any scanning gets started or connecting to existing peripherals happens, it's never already in a
  21.200 +		// powered-on state for a newly launched application.
  21.201 +		sharedInstance.centralManager = [[CBCentralManager alloc] initWithDelegate:sharedInstance queue:sharedInstance.bleSerialQueue];
  21.202 +		sharedInstance.deviceMap = [[NSMapTable alloc] initWithKeyOptions:NSMapTableWeakMemory valueOptions:NSMapTableStrongMemory capacity:4];
  21.203 +	});
  21.204 +	return sharedInstance;
  21.205 +}
  21.206 +
  21.207 +// called for NSNotification UIApplicationWillResignActiveNotification
  21.208 +- (void)appWillResignActiveNotification:(NSNotification *)note
  21.209 +{
  21.210 +	// we'll get resign-active notification if pairing is happening.
  21.211 +	if ( self.nPendingPairs > 0 )
  21.212 +		return;
  21.213 +
  21.214 +	for ( CBPeripheral *peripheral in self.deviceMap )
  21.215 +	{
  21.216 +		HIDBLEDevice *steamController = [self.deviceMap objectForKey:peripheral];
  21.217 +		if ( steamController )
  21.218 +		{
  21.219 +			steamController.connected = NO;
  21.220 +			steamController.ready = NO;
  21.221 +			[self.centralManager cancelPeripheralConnection:peripheral];
  21.222 +		}
  21.223 +	}
  21.224 +	[self.deviceMap removeAllObjects];
  21.225 +}
  21.226 +
  21.227 +// called for NSNotification UIApplicationDidBecomeActiveNotification
  21.228 +//  whenever the application comes back from being inactive, trigger a 20s pairing scan and reconnect
  21.229 +//  any devices that may have paired while we were inactive.
  21.230 +- (void)appDidBecomeActiveNotification:(NSNotification *)note
  21.231 +{
  21.232 +	[self updateConnectedSteamControllers:true];
  21.233 +	[self startScan:20];
  21.234 +}
  21.235 +
  21.236 +- (int)updateConnectedSteamControllers:(BOOL) bForce
  21.237 +{
  21.238 +	static uint64_t s_unLastUpdateTick = 0;
  21.239 +	static mach_timebase_info_data_t s_timebase_info;
  21.240 +	
  21.241 +	if (s_timebase_info.denom == 0)
  21.242 +	{
  21.243 +		mach_timebase_info( &s_timebase_info );
  21.244 +	}
  21.245 +	
  21.246 +	uint64_t ticksNow = mach_approximate_time();
  21.247 +	if ( !bForce && ( ( (ticksNow - s_unLastUpdateTick) * s_timebase_info.numer ) / s_timebase_info.denom ) < (5ull * NSEC_PER_SEC) )
  21.248 +		return (int)self.deviceMap.count;
  21.249 +	
  21.250 +	// we can see previously connected BLE peripherals but can't connect until the CBCentralManager
  21.251 +	// is fully powered up - only do work when we are in that state
  21.252 +	if ( self.centralManager.state != CBManagerStatePoweredOn )
  21.253 +		return (int)self.deviceMap.count;
  21.254 +
  21.255 +	// only update our last-check-time if we actually did work, otherwise there can be a long delay during initial power-up
  21.256 +	s_unLastUpdateTick = mach_approximate_time();
  21.257 +	
  21.258 +	// if a pair is in-flight, the central manager may still give it back via retrieveConnected... and
  21.259 +	// cause the SDL layer to attempt to initialize it while some of its endpoints haven't yet been established
  21.260 +	if ( self.nPendingPairs > 0 )
  21.261 +		return (int)self.deviceMap.count;
  21.262 +
  21.263 +	NSArray<CBPeripheral *> *peripherals = [self.centralManager retrieveConnectedPeripheralsWithServices: @[ [CBUUID UUIDWithString:@"180A"]]];
  21.264 +	for ( CBPeripheral *peripheral in peripherals )
  21.265 +	{
  21.266 +		// we already know this peripheral
  21.267 +		if ( [self.deviceMap objectForKey: peripheral] != nil )
  21.268 +			continue;
  21.269 +		
  21.270 +		NSLog( @"connected peripheral: %@", peripheral );
  21.271 +		if ( [peripheral.name isEqualToString:@"SteamController"] )
  21.272 +		{
  21.273 +			HIDBLEDevice *steamController = [[HIDBLEDevice alloc] initWithPeripheral:peripheral];
  21.274 +			[self.deviceMap setObject:steamController forKey:peripheral];
  21.275 +			[self.centralManager connectPeripheral:peripheral options:nil];
  21.276 +		}
  21.277 +	}
  21.278 +
  21.279 +	return (int)self.deviceMap.count;
  21.280 +}
  21.281 +
  21.282 +// manual API for folks to start & stop scanning
  21.283 +- (void)startScan:(int)duration
  21.284 +{
  21.285 +	NSLog( @"BLE: requesting scan for %d seconds", duration );
  21.286 +	@synchronized (self)
  21.287 +	{
  21.288 +		if ( _nPendingScans++ == 0 )
  21.289 +		{
  21.290 +			[self.centralManager scanForPeripheralsWithServices:nil options:nil];
  21.291 +		}
  21.292 +	}
  21.293 +
  21.294 +	if ( duration != 0 )
  21.295 +	{
  21.296 +		dispatch_after( dispatch_time( DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  21.297 +			[self stopScan];
  21.298 +		});
  21.299 +	}
  21.300 +}
  21.301 +
  21.302 +- (void)stopScan
  21.303 +{
  21.304 +	NSLog( @"BLE: stopping scan" );
  21.305 +	@synchronized (self)
  21.306 +	{
  21.307 +		if ( --_nPendingScans <= 0 )
  21.308 +		{
  21.309 +			_nPendingScans = 0;
  21.310 +			[self.centralManager stopScan];
  21.311 +		}
  21.312 +	}
  21.313 +}
  21.314 +
  21.315 +
  21.316 +#pragma mark CBCentralManagerDelegate Implementation
  21.317 +
  21.318 +// called whenever the BLE hardware state changes.
  21.319 +- (void)centralManagerDidUpdateState:(CBCentralManager *)central
  21.320 +{
  21.321 +	switch ( central.state )
  21.322 +	{
  21.323 +		case CBCentralManagerStatePoweredOn:
  21.324 +		{
  21.325 +			NSLog( @"CoreBluetooth BLE hardware is powered on and ready" );
  21.326 +			
  21.327 +			// at startup, if we have no already attached peripherals, do a 20s scan for new unpaired devices,
  21.328 +			// otherwise callers should occaisionally do additional scans. we don't want to continuously be
  21.329 +			// scanning because it drains battery, causes other nearby people to have a hard time pairing their
  21.330 +			// Steam Controllers, and may also trigger firmware weirdness when a device attempts to start
  21.331 +			// the pairing sequence multiple times concurrently
  21.332 +			if ( [self updateConnectedSteamControllers:false] == 0 )
  21.333 +			{
  21.334 +				// TODO: we could limit our scan to only peripherals supporting the SteamController service, but
  21.335 +				//  that service doesn't currently fit in the base advertising packet, we'd need to put it into an
  21.336 +				//  extended scan packet. Useful optimization downstream, but not currently necessary
  21.337 +				//	NSArray *services = @[[CBUUID UUIDWithString:VALVE_SERVICE]];
  21.338 +				[self startScan:20];
  21.339 +			}
  21.340 +			break;
  21.341 +		}
  21.342 +			
  21.343 +		case CBCentralManagerStatePoweredOff:
  21.344 +			NSLog( @"CoreBluetooth BLE hardware is powered off" );
  21.345 +			break;
  21.346 +			
  21.347 +		case CBCentralManagerStateUnauthorized:
  21.348 +			NSLog( @"CoreBluetooth BLE state is unauthorized" );
  21.349 +			break;
  21.350 +			
  21.351 +		case CBCentralManagerStateUnknown:
  21.352 +			NSLog( @"CoreBluetooth BLE state is unknown" );
  21.353 +			break;
  21.354 +			
  21.355 +		case CBCentralManagerStateUnsupported:
  21.356 +			NSLog( @"CoreBluetooth BLE hardware is unsupported on this platform" );
  21.357 +			break;
  21.358 +		
  21.359 +		case CBCentralManagerStateResetting:
  21.360 +			NSLog( @"CoreBluetooth BLE manager is resetting" );
  21.361 +			break;
  21.362 +	}
  21.363 +}
  21.364 +
  21.365 +- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
  21.366 +{
  21.367 +	HIDBLEDevice *steamController = [_deviceMap objectForKey:peripheral];
  21.368 +	steamController.connected = YES;
  21.369 +	self.nPendingPairs -= 1;
  21.370 +}
  21.371 +
  21.372 +- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
  21.373 +{
  21.374 +	NSLog( @"Failed to connect: %@", error );
  21.375 +	[_deviceMap removeObjectForKey:peripheral];
  21.376 +	self.nPendingPairs -= 1;
  21.377 +}
  21.378 +
  21.379 +- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
  21.380 +{
  21.381 +	NSString *localName = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey];
  21.382 +	NSString *log = [NSString stringWithFormat:@"Found '%@'", localName];
  21.383 +	
  21.384 +	if ( [localName isEqualToString:@"SteamController"] )
  21.385 +	{
  21.386 +		NSLog( @"%@ : %@ - %@", log, peripheral, advertisementData );
  21.387 +		self.nPendingPairs += 1;
  21.388 +		HIDBLEDevice *steamController = [[HIDBLEDevice alloc] initWithPeripheral:peripheral];
  21.389 +		[self.deviceMap setObject:steamController forKey:peripheral];
  21.390 +		[self.centralManager connectPeripheral:peripheral options:nil];
  21.391 +	}
  21.392 +}
  21.393 +
  21.394 +- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
  21.395 +{
  21.396 +	HIDBLEDevice *steamController = [self.deviceMap objectForKey:peripheral];
  21.397 +	if ( steamController )
  21.398 +	{
  21.399 +		steamController.connected = NO;
  21.400 +		steamController.ready = NO;
  21.401 +		[self.deviceMap removeObjectForKey:peripheral];
  21.402 +	}
  21.403 +}
  21.404 +
  21.405 +@end
  21.406 +
  21.407 +
  21.408 +// Core Bluetooth devices calling back on event boundaries of their run-loops. so annoying.
  21.409 +static void process_pending_events()
  21.410 +{
  21.411 +	CFRunLoopRunResult res;
  21.412 +	do
  21.413 +	{
  21.414 +		res = CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0.001, FALSE );
  21.415 +	}
  21.416 +	while( res != kCFRunLoopRunFinished && res != kCFRunLoopRunTimedOut );
  21.417 +}
  21.418 +
  21.419 +@implementation HIDBLEDevice
  21.420 +
  21.421 +- (id)init
  21.422 +{
  21.423 +	if ( self = [super init] )
  21.424 +	{
  21.425 +		self.bleSteamController = nil;
  21.426 +		self.bleCharacteristicInput = nil;
  21.427 +		self.bleCharacteristicReport = nil;
  21.428 +		_connected = NO;
  21.429 +		_ready = NO;
  21.430 +	}
  21.431 +	return self;
  21.432 +}
  21.433 +
  21.434 +- (id)initWithPeripheral:(CBPeripheral *)peripheral
  21.435 +{
  21.436 +	if ( self = [super init] )
  21.437 +	{
  21.438 +		_connected = NO;
  21.439 +		_ready = NO;
  21.440 +		self.bleSteamController = peripheral;
  21.441 +		if ( peripheral )
  21.442 +		{
  21.443 +			peripheral.delegate = self;
  21.444 +		}
  21.445 +		self.bleCharacteristicInput = nil;
  21.446 +		self.bleCharacteristicReport = nil;
  21.447 +	}
  21.448 +	return self;
  21.449 +}
  21.450 +
  21.451 +- (void)setConnected:(bool)connected
  21.452 +{
  21.453 +	_connected = connected;
  21.454 +	if ( _connected )
  21.455 +	{
  21.456 +		[_bleSteamController discoverServices:nil];
  21.457 +	}
  21.458 +	else
  21.459 +	{
  21.460 +		NSLog( @"Disconnected" );
  21.461 +	}
  21.462 +}
  21.463 +
  21.464 +- (size_t)read_input_report:(uint8_t *)dst
  21.465 +{
  21.466 +	if ( _inputReports.read( dst+1 ) )
  21.467 +	{
  21.468 +		*dst = 0x03;
  21.469 +		return 20;
  21.470 +	}
  21.471 +	return 0;
  21.472 +}
  21.473 +
  21.474 +- (int)send_report:(const uint8_t *)data length:(size_t)length
  21.475 +{
  21.476 +	[_bleSteamController writeValue:[NSData dataWithBytes:data length:length] forCharacteristic:_bleCharacteristicReport type:CBCharacteristicWriteWithResponse];
  21.477 +	return (int)length;
  21.478 +}
  21.479 +
  21.480 +- (int)send_feature_report:(hidFeatureReport *)report
  21.481 +{
  21.482 +#if FEATURE_REPORT_LOGGING
  21.483 +	uint8_t *reportBytes = (uint8_t *)report;
  21.484 +	
  21.485 +	NSLog( @"HIDBLE:send_feature_report (%02zu/19) [%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]", report->segment.size(),
  21.486 +		  reportBytes[1], reportBytes[2], reportBytes[3], reportBytes[4], reportBytes[5], reportBytes[6],
  21.487 +		  reportBytes[7], reportBytes[8], reportBytes[9], reportBytes[10], reportBytes[11], reportBytes[12],
  21.488 +		  reportBytes[13], reportBytes[14], reportBytes[15], reportBytes[16], reportBytes[17], reportBytes[18],
  21.489 +		  reportBytes[19] );
  21.490 +#endif
  21.491 +
  21.492 +	int sendSize = (int)report->segment.size();
  21.493 +	if ( sendSize > 20 )
  21.494 +		sendSize = 20;
  21.495 +
  21.496 +#if 1
  21.497 +	// fire-and-forget - we are going to not wait for the response here because all Steam Controller BLE send_feature_report's are ignored,
  21.498 +	//  except errors.
  21.499 +	[_bleSteamController writeValue:[NSData dataWithBytes:&report->segment length:sendSize] forCharacteristic:_bleCharacteristicReport type:CBCharacteristicWriteWithResponse];
  21.500 +	
  21.501 +	// pretend we received a result anybody cares about
  21.502 +	return 19;
  21.503 +
  21.504 +#else
  21.505 +	// this is technically the correct send_feature_report logic if you want to make sure it gets through and is
  21.506 +	// acknowledged or errors out
  21.507 +	_waitStateForWriteFeatureReport = BLEDeviceWaitState::Waiting;
  21.508 +	[_bleSteamController writeValue:[NSData dataWithBytes:&report->segment length:sendSize
  21.509 +									 ] forCharacteristic:_bleCharacteristicReport type:CBCharacteristicWriteWithResponse];
  21.510 +	
  21.511 +	while ( _waitStateForWriteFeatureReport == BLEDeviceWaitState::Waiting )
  21.512 +	{
  21.513 +		process_pending_events();
  21.514 +	}
  21.515 +	
  21.516 +	if ( _waitStateForWriteFeatureReport == BLEDeviceWaitState::Error )
  21.517 +	{
  21.518 +		_waitStateForWriteFeatureReport = BLEDeviceWaitState::None;
  21.519 +		return -1;
  21.520 +	}
  21.521 +	
  21.522 +	_waitStateForWriteFeatureReport = BLEDeviceWaitState::None;
  21.523 +	return 19;
  21.524 +#endif
  21.525 +}
  21.526 +
  21.527 +- (int)get_feature_report:(uint8_t)feature into:(uint8_t *)buffer
  21.528 +{
  21.529 +	_waitStateForReadFeatureReport = BLEDeviceWaitState::Waiting;
  21.530 +	[_bleSteamController readValueForCharacteristic:_bleCharacteristicReport];
  21.531 +	
  21.532 +	while ( _waitStateForReadFeatureReport == BLEDeviceWaitState::Waiting )
  21.533 +		process_pending_events();
  21.534 +	
  21.535 +	if ( _waitStateForReadFeatureReport == BLEDeviceWaitState::Error )
  21.536 +	{
  21.537 +		_waitStateForReadFeatureReport = BLEDeviceWaitState::None;
  21.538 +		return -1;
  21.539 +	}
  21.540 +	
  21.541 +	memcpy( buffer, _featureReport, sizeof(_featureReport) );
  21.542 +	
  21.543 +	_waitStateForReadFeatureReport = BLEDeviceWaitState::None;
  21.544 +	
  21.545 +#if FEATURE_REPORT_LOGGING
  21.546 +	NSLog( @"HIDBLE:get_feature_report (19) [%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]",
  21.547 +		  buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6],
  21.548 +		  buffer[7], buffer[8], buffer[9], buffer[10], buffer[11], buffer[12],
  21.549 +		  buffer[13], buffer[14], buffer[15], buffer[16], buffer[17], buffer[18],
  21.550 +		  buffer[19] );
  21.551 +#endif
  21.552 +
  21.553 +	return 19;
  21.554 +}
  21.555 +
  21.556 +#pragma mark CBPeripheralDelegate Implementation
  21.557 +
  21.558 +- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
  21.559 +{
  21.560 +	for (CBService *service in peripheral.services)
  21.561 +	{
  21.562 +		NSLog( @"Found Service: %@", service );
  21.563 +		if ( [service.UUID isEqual:[CBUUID UUIDWithString:VALVE_SERVICE]] )
  21.564 +		{
  21.565 +			[peripheral discoverCharacteristics:nil forService:service];
  21.566 +		}
  21.567 +	}
  21.568 +}
  21.569 +
  21.570 +- (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
  21.571 +{
  21.572 +	// nothing yet needed here, enable for logging
  21.573 +	if ( /* DISABLES CODE */ (0) )
  21.574 +	{
  21.575 +		for ( CBDescriptor *descriptor in characteristic.descriptors )
  21.576 +		{
  21.577 +			NSLog( @" - Descriptor '%@'", descriptor );
  21.578 +		}
  21.579 +	}
  21.580 +}
  21.581 +
  21.582 +- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
  21.583 +{
  21.584 +	if ([service.UUID isEqual:[CBUUID UUIDWithString:VALVE_SERVICE]])
  21.585 +	{
  21.586 +		for (CBCharacteristic *aChar in service.characteristics)
  21.587 +		{
  21.588 +			NSLog( @"Found Characteristic %@", aChar );
  21.589 +			
  21.590 +			if ( [aChar.UUID isEqual:[CBUUID UUIDWithString:VALVE_INPUT_CHAR]] )
  21.591 +			{
  21.592 +				self.bleCharacteristicInput = aChar;
  21.593 +			}
  21.594 +			else if ( [aChar.UUID isEqual:[CBUUID UUIDWithString:VALVE_REPORT_CHAR]] )
  21.595 +			{
  21.596 +				self.bleCharacteristicReport = aChar;
  21.597 +				[self.bleSteamController discoverDescriptorsForCharacteristic: aChar];
  21.598 +			}
  21.599 +		}
  21.600 +	}
  21.601 +}
  21.602 +
  21.603 +- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
  21.604 +{
  21.605 +	static uint64_t s_ticksLastOverflowReport = 0;
  21.606 +
  21.607 +	// receiving an input report is the final indicator that the user accepted a pairing
  21.608 +	// request and that we successfully established notification. CoreBluetooth has no
  21.609 +	// notification of the pairing acknowledgement, which is a bad oversight.
  21.610 +	if ( self.ready == NO )
  21.611 +	{
  21.612 +		self.ready = YES;
  21.613 +		HIDBLEManager.sharedInstance.nPendingPairs -= 1;
  21.614 +	}
  21.615 +
  21.616 +	if ( [characteristic.UUID isEqual:_bleCharacteristicInput.UUID] )
  21.617 +	{
  21.618 +		NSData *data = [characteristic value];
  21.619 +		if ( data.length != 19 )
  21.620 +		{
  21.621 +			NSLog( @"HIDBLE: incoming data is %lu bytes should be exactly 19", (unsigned long)data.length );
  21.622 +		}
  21.623 +		if ( !_inputReports.write( (const uint8_t *)data.bytes ) )
  21.624 +		{
  21.625 +			uint64_t ticksNow = mach_approximate_time();
  21.626 +			if ( ticksNow - s_ticksLastOverflowReport > (5ull * NSEC_PER_SEC / 10) )
  21.627 +			{
  21.628 +				NSLog( @"HIDBLE: input report buffer overflow" );
  21.629 +				s_ticksLastOverflowReport = ticksNow;
  21.630 +			}
  21.631 +		}
  21.632 +	}
  21.633 +	else if ( [characteristic.UUID isEqual:_bleCharacteristicReport.UUID] )
  21.634 +	{
  21.635 +		memset( _featureReport, 0, sizeof(_featureReport) );
  21.636 +		
  21.637 +		if ( error != nil )
  21.638 +		{
  21.639 +			NSLog( @"HIDBLE: get_feature_report error: %@", error );
  21.640 +			_waitStateForReadFeatureReport = BLEDeviceWaitState::Error;
  21.641 +		}
  21.642 +		else
  21.643 +		{
  21.644 +			NSData *data = [characteristic value];
  21.645 +			if ( data.length != 20 )
  21.646 +			{
  21.647 +				NSLog( @"HIDBLE: incoming data is %lu bytes should be exactly 20", (unsigned long)data.length );
  21.648 +			}
  21.649 +			memcpy( _featureReport, data.bytes, MIN( data.length, sizeof(_featureReport) ) );
  21.650 +			_waitStateForReadFeatureReport = BLEDeviceWaitState::Complete;
  21.651 +		}
  21.652 +	}
  21.653 +}
  21.654 +
  21.655 +- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
  21.656 +{
  21.657 +	if ( [characteristic.UUID isEqual:[CBUUID UUIDWithString:VALVE_REPORT_CHAR]] )
  21.658 +	{
  21.659 +		if ( error != nil )
  21.660 +		{
  21.661 +			NSLog( @"HIDBLE: write_feature_report error: %@", error );
  21.662 +			_waitStateForWriteFeatureReport = BLEDeviceWaitState::Error;
  21.663 +		}
  21.664 +		else
  21.665 +		{
  21.666 +			_waitStateForWriteFeatureReport = BLEDeviceWaitState::Complete;
  21.667 +		}
  21.668 +	}
  21.669 +}
  21.670 +
  21.671 +- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
  21.672 +{
  21.673 +	NSLog( @"didUpdateNotifcationStateForCharacteristic %@ (%@)", characteristic, error );
  21.674 +}
  21.675 +
  21.676 +@end
  21.677 +
  21.678 +
  21.679 +#pragma mark hid_api implementation
  21.680 +
  21.681 +struct hid_device_ {
  21.682 +	HIDBLEDevice *device_handle;
  21.683 +	int blocking;
  21.684 +	hid_device *next;
  21.685 +};
  21.686 +
  21.687 +int HID_API_EXPORT HID_API_CALL hid_init(void)
  21.688 +{
  21.689 +	return ( HIDBLEManager.sharedInstance == nil ) ? -1 : 0;
  21.690 +}
  21.691 +
  21.692 +int HID_API_EXPORT HID_API_CALL hid_exit(void)
  21.693 +{
  21.694 +	return 0;
  21.695 +}
  21.696 +
  21.697 +void HID_API_EXPORT HID_API_CALL hid_ble_scan( bool bStart )
  21.698 +{
  21.699 +	HIDBLEManager *bleManager = HIDBLEManager.sharedInstance;
  21.700 +	if ( bStart )
  21.701 +	{
  21.702 +		[bleManager startScan:0];
  21.703 +	}
  21.704 +	else
  21.705 +	{
  21.706 +		[bleManager stopScan];
  21.707 +	}
  21.708 +}
  21.709 +
  21.710 +hid_device * HID_API_EXPORT hid_open_path( const char *path, int bExclusive /* = false */ )
  21.711 +{
  21.712 +	hid_device *result = NULL;
  21.713 +	NSString *nssPath = [NSString stringWithUTF8String:path];
  21.714 +	HIDBLEManager *bleManager = HIDBLEManager.sharedInstance;
  21.715 +	NSEnumerator<HIDBLEDevice *> *devices = [bleManager.deviceMap objectEnumerator];
  21.716 +	
  21.717 +	for ( HIDBLEDevice *device in devices )
  21.718 +	{
  21.719 +		// we have the device but it hasn't found its service or characteristics until it is connected
  21.720 +		if ( !device.ready || !device.connected || !device.bleCharacteristicInput )
  21.721 +			continue;
  21.722 +		
  21.723 +		if ( [device.bleSteamController.identifier.UUIDString isEqualToString:nssPath] )
  21.724 +		{
  21.725 +			result = (hid_device *)malloc( sizeof( hid_device ) );
  21.726 +			memset( result, 0, sizeof( hid_device ) );
  21.727 +			result->device_handle = device;
  21.728 +			result->blocking = NO;
  21.729 +			// enable reporting input events on the characteristic
  21.730 +			[device.bleSteamController setNotifyValue:YES forCharacteristic:device.bleCharacteristicInput];
  21.731 +			return result;
  21.732 +		}
  21.733 +	}
  21.734 +	return result;
  21.735 +}
  21.736 +
  21.737 +void  HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
  21.738 +{
  21.739 +	/* This function is identical to the Linux version. Platform independent. */
  21.740 +	struct hid_device_info *d = devs;
  21.741 +	while (d) {
  21.742 +		struct hid_device_info *next = d->next;
  21.743 +		free(d->path);
  21.744 +		free(d->serial_number);
  21.745 +		free(d->manufacturer_string);
  21.746 +		free(d->product_string);
  21.747 +		free(d);
  21.748 +		d = next;
  21.749 +	}
  21.750 +}
  21.751 +
  21.752 +int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
  21.753 +{
  21.754 +	/* All Nonblocking operation is handled by the library. */
  21.755 +	dev->blocking = !nonblock;
  21.756 +	
  21.757 +	return 0;
  21.758 +}
  21.759 +
  21.760 +struct hid_device_info  HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
  21.761 +{ @autoreleasepool {
  21.762 +	struct hid_device_info *root = NULL;
  21.763 +	
  21.764 +	if ( ( vendor_id == 0 && product_id == 0 ) ||
  21.765 +		 ( vendor_id == VALVE_USB_VID && product_id == D0G_BLE2_PID ) )
  21.766 +	{
  21.767 +		HIDBLEManager *bleManager = HIDBLEManager.sharedInstance;
  21.768 +		[bleManager updateConnectedSteamControllers:false];
  21.769 +		NSEnumerator<HIDBLEDevice *> *devices = [bleManager.deviceMap objectEnumerator];
  21.770 +		for ( HIDBLEDevice *device in devices )
  21.771 +		{
  21.772 +			// there are several brief windows in connecting to an already paired device and
  21.773 +			// one long window waiting for users to confirm pairing where we don't want
  21.774 +			// to consider a device ready - if we hand it back to SDL or another
  21.775 +			// Steam Controller consumer, their additional SC setup work will fail
  21.776 +			// in unusual/silent ways and we can actually corrupt the BLE stack for
  21.777 +			// the entire system and kill the appletv remote's Menu button (!)
  21.778 +			if ( device.bleSteamController.state != CBPeripheralStateConnected ||
  21.779 +				 device.connected == NO || device.ready == NO )
  21.780 +			{
  21.781 +				if ( device.ready == NO && device.bleCharacteristicInput != nil )
  21.782 +				{
  21.783 +					// attempt to register for input reports. this call will silently fail
  21.784 +					// until the pairing finalizes with user acceptance. oh, apple.
  21.785 +					[device.bleSteamController setNotifyValue:YES forCharacteristic:device.bleCharacteristicInput];
  21.786 +				}
  21.787 +				continue;
  21.788 +			}
  21.789 +			hid_device_info *device_info = (hid_device_info *)malloc( sizeof(hid_device_info) );
  21.790 +			memset( device_info, 0, sizeof(hid_device_info) );
  21.791 +			device_info->next = root;
  21.792 +			root = device_info;
  21.793 +			device_info->path = strdup( device.bleSteamController.identifier.UUIDString.UTF8String );
  21.794 +			device_info->vendor_id = VALVE_USB_VID;
  21.795 +			device_info->product_id = D0G_BLE2_PID;
  21.796 +			device_info->product_string = wcsdup( L"Steam Controller" );
  21.797 +			device_info->manufacturer_string = wcsdup( L"Valve Corporation" );
  21.798 +		}
  21.799 +	}
  21.800 +	return root;
  21.801 +}}
  21.802 +
  21.803 +int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
  21.804 +{
  21.805 +	static wchar_t s_wszManufacturer[] = L"Valve Corporation";
  21.806 +	wcsncpy( string, s_wszManufacturer, sizeof(s_wszManufacturer)/sizeof(s_wszManufacturer[0]) );
  21.807 +	return 0;
  21.808 +}
  21.809 +
  21.810 +int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
  21.811 +{
  21.812 +	static wchar_t s_wszProduct[] = L"Steam Controller";
  21.813 +	wcsncpy( string, s_wszProduct, sizeof(s_wszProduct)/sizeof(s_wszProduct[0]) );
  21.814 +	return 0;
  21.815 +}
  21.816 +
  21.817 +int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
  21.818 +{
  21.819 +	static wchar_t s_wszSerial[] = L"12345";
  21.820 +	wcsncpy( string, s_wszSerial, sizeof(s_wszSerial)/sizeof(s_wszSerial[0]) );
  21.821 +	return 0;
  21.822 +}
  21.823 +
  21.824 +int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
  21.825 +{
  21.826 +	if ( !dev->device_handle.connected )
  21.827 +		return -1;
  21.828 +
  21.829 +	return [dev->device_handle send_report:data length:length];
  21.830 +}
  21.831 +
  21.832 +void HID_API_EXPORT hid_close(hid_device *dev)
  21.833 +{
  21.834 +	// disable reporting input events on the characteristic
  21.835 +	if ( dev->device_handle.connected ) {
  21.836 +		[dev->device_handle.bleSteamController setNotifyValue:NO forCharacteristic:dev->device_handle.bleCharacteristicInput];
  21.837 +	}
  21.838 +
  21.839 +	free( dev );
  21.840 +}
  21.841 +
  21.842 +int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
  21.843 +{
  21.844 +	if ( !dev->device_handle.connected )
  21.845 +		return -1;
  21.846 +
  21.847 +	return [dev->device_handle send_feature_report:(hidFeatureReport *)(void *)data];
  21.848 +}
  21.849 +
  21.850 +int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
  21.851 +{
  21.852 +	if ( !dev->device_handle.connected )
  21.853 +		return -1;
  21.854 +
  21.855 +	size_t written = [dev->device_handle get_feature_report:data[0] into:data];
  21.856 +	
  21.857 +	return written == length-1 ? (int)length : (int)written;
  21.858 +}
  21.859 +
  21.860 +int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
  21.861 +{
  21.862 +	if ( !dev->device_handle.connected )
  21.863 +		return -1;
  21.864 +
  21.865 +	return hid_read_timeout(dev, data, length, 0);
  21.866 +}
  21.867 +
  21.868 +int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
  21.869 +{
  21.870 +	if ( !dev->device_handle.connected )
  21.871 +		return -1;
  21.872 +	
  21.873 +	if ( milliseconds != 0 )
  21.874 +	{
  21.875 +		NSLog( @"hid_read_timeout with non-zero wait" );
  21.876 +	}
  21.877 +	int result = (int)[dev->device_handle read_input_report:data];
  21.878 +#if FEATURE_REPORT_LOGGING
  21.879 +	NSLog( @"HIDBLE:hid_read_timeout (%d) [%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]", result,
  21.880 +		  data[1], data[2], data[3], data[4], data[5], data[6],
  21.881 +		  data[7], data[8], data[9], data[10], data[11], data[12],
  21.882 +		  data[13], data[14], data[15], data[16], data[17], data[18],
  21.883 +		  data[19] );
  21.884 +#endif
  21.885 +	return result;
  21.886 +}
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/src/hidapi/libusb/Makefile-manual	Thu Aug 09 16:05:48 2018 -0700
    22.3 @@ -0,0 +1,18 @@
    22.4 +
    22.5 +
    22.6 +OS=$(shell uname)
    22.7 +
    22.8 +ifeq ($(OS), Linux)
    22.9 +	FILE=Makefile.linux
   22.10 +endif
   22.11 +
   22.12 +ifeq ($(OS), FreeBSD)
   22.13 +	FILE=Makefile.freebsd
   22.14 +endif
   22.15 +
   22.16 +ifeq ($(FILE), )
   22.17 +all:
   22.18 +	$(error Your platform ${OS} is not supported by hidapi/libusb at this time.)
   22.19 +endif
   22.20 +
   22.21 +include $(FILE)
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/src/hidapi/libusb/Makefile.am	Thu Aug 09 16:05:48 2018 -0700
    23.3 @@ -0,0 +1,27 @@
    23.4 +AM_CPPFLAGS = -I$(top_srcdir)/hidapi $(CFLAGS_LIBUSB)
    23.5 +
    23.6 +if OS_LINUX
    23.7 +lib_LTLIBRARIES = libhidapi-libusb.la
    23.8 +libhidapi_libusb_la_SOURCES = hid.c
    23.9 +libhidapi_libusb_la_LDFLAGS = $(LTLDFLAGS) $(PTHREAD_CFLAGS)
   23.10 +libhidapi_libusb_la_LIBADD = $(LIBS_LIBUSB)
   23.11 +endif
   23.12 +
   23.13 +if OS_FREEBSD
   23.14 +lib_LTLIBRARIES = libhidapi.la
   23.15 +libhidapi_la_SOURCES = hid.c
   23.16 +libhidapi_la_LDFLAGS = $(LTLDFLAGS)
   23.17 +libhidapi_la_LIBADD = $(LIBS_LIBUSB)
   23.18 +endif
   23.19 +
   23.20 +if OS_KFREEBSD
   23.21 +lib_LTLIBRARIES = libhidapi.la
   23.22 +libhidapi_la_SOURCES = hid.c
   23.23 +libhidapi_la_LDFLAGS = $(LTLDFLAGS)
   23.24 +libhidapi_la_LIBADD = $(LIBS_LIBUSB)
   23.25 +endif
   23.26 +
   23.27 +hdrdir = $(includedir)/hidapi
   23.28 +hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h
   23.29 +
   23.30 +EXTRA_DIST = Makefile-manual
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/src/hidapi/libusb/Makefile.freebsd	Thu Aug 09 16:05:48 2018 -0700
    24.3 @@ -0,0 +1,46 @@
    24.4 +###########################################
    24.5 +# Simple Makefile for HIDAPI test program
    24.6 +#
    24.7 +# Alan Ott
    24.8 +# Signal 11 Software
    24.9 +# 2010-06-01
   24.10 +###########################################
   24.11 +
   24.12 +all: hidtest libs
   24.13 +
   24.14 +libs: libhidapi.so
   24.15 +
   24.16 +CC       ?= cc
   24.17 +CFLAGS   ?= -Wall -g -fPIC
   24.18 +
   24.19 +CXX      ?= c++
   24.20 +CXXFLAGS ?= -Wall -g
   24.21 +
   24.22 +COBJS     = hid.o
   24.23 +CPPOBJS   = ../hidtest/hidtest.o
   24.24 +OBJS      = $(COBJS) $(CPPOBJS)
   24.25 +INCLUDES  = -I../hidapi -I/usr/local/include
   24.26 +LDFLAGS   = -L/usr/local/lib
   24.27 +LIBS      = -lusb -liconv -pthread
   24.28 +
   24.29 +
   24.30 +# Console Test Program
   24.31 +hidtest: $(OBJS)
   24.32 +	$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS)
   24.33 +
   24.34 +# Shared Libs
   24.35 +libhidapi.so: $(COBJS)
   24.36 +	$(CC) $(LDFLAGS) -shared -Wl,-soname,$@.0 $^ -o $@ $(LIBS)
   24.37 +
   24.38 +# Objects
   24.39 +$(COBJS): %.o: %.c
   24.40 +	$(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@
   24.41 +
   24.42 +$(CPPOBJS): %.o: %.cpp
   24.43 +	$(CXX) $(CXXFLAGS) -c $(INCLUDES) $< -o $@
   24.44 +
   24.45 +
   24.46 +clean:
   24.47 +	rm -f $(OBJS) hidtest libhidapi.so ../hidtest/hidtest.o
   24.48 +
   24.49 +.PHONY: clean libs
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/src/hidapi/libusb/Makefile.linux	Thu Aug 09 16:05:48 2018 -0700
    25.3 @@ -0,0 +1,49 @@
    25.4 +###########################################
    25.5 +# Simple Makefile for HIDAPI test program
    25.6 +#
    25.7 +# Alan Ott
    25.8 +# Signal 11 Software
    25.9 +# 2010-06-01
   25.10 +###########################################
   25.11 +
   25.12 +all: hidtest-libusb libs
   25.13 +
   25.14 +libs: libhidapi-libusb.so
   25.15 +
   25.16 +CC       ?= gcc
   25.17 +CFLAGS   ?= -Wall -g -fpic
   25.18 +
   25.19 +CXX      ?= g++
   25.20 +CXXFLAGS ?= -Wall -g -fpic
   25.21 +
   25.22 +LDFLAGS  ?= -Wall -g
   25.23 +
   25.24 +COBJS_LIBUSB = hid.o
   25.25 +COBJS = $(COBJS_LIBUSB)
   25.26 +CPPOBJS   = ../hidtest/hidtest.o
   25.27 +OBJS      = $(COBJS) $(CPPOBJS)
   25.28 +LIBS_USB  = `pkg-config libusb-1.0 --libs` -lrt -lpthread
   25.29 +LIBS      = $(LIBS_USB)
   25.30 +INCLUDES ?= -I../hidapi `pkg-config libusb-1.0 --cflags`
   25.31 +
   25.32 +
   25.33 +# Console Test Program
   25.34 +hidtest-libusb: $(COBJS_LIBUSB) $(CPPOBJS)
   25.35 +	$(CXX) $(LDFLAGS) $^ $(LIBS_USB) -o $@
   25.36 +
   25.37 +# Shared Libs
   25.38 +libhidapi-libusb.so: $(COBJS_LIBUSB)
   25.39 +	$(CC) $(LDFLAGS) $(LIBS_USB) -shared -fpic -Wl,-soname,$@.0 $^ -o $@
   25.40 +
   25.41 +# Objects
   25.42 +$(COBJS): %.o: %.c
   25.43 +	$(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@
   25.44 +
   25.45 +$(CPPOBJS): %.o: %.cpp
   25.46 +	$(CXX) $(CXXFLAGS) -c $(INCLUDES) $< -o $@
   25.47 +
   25.48 +
   25.49 +clean:
   25.50 +	rm -f $(OBJS) hidtest-libusb libhidapi-libusb.so ../hidtest/hidtest.o
   25.51 +
   25.52 +.PHONY: clean libs
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/src/hidapi/libusb/hid.c	Thu Aug 09 16:05:48 2018 -0700
    26.3 @@ -0,0 +1,1615 @@
    26.4 +/*******************************************************
    26.5 + HIDAPI - Multi-Platform library for
    26.6 + communication with HID devices.
    26.7 +
    26.8 + Alan Ott
    26.9 + Signal 11 Software
   26.10 +
   26.11 + 8/22/2009
   26.12 + Linux Version - 6/2/2010
   26.13 + Libusb Version - 8/13/2010
   26.14 + FreeBSD Version - 11/1/2011
   26.15 +
   26.16 + Copyright 2009, All Rights Reserved.
   26.17 +
   26.18 + At the discretion of the user of this library,
   26.19 + this software may be licensed under the terms of the
   26.20 + GNU General Public License v3, a BSD-Style license, or the
   26.21 + original HIDAPI license as outlined in the LICENSE.txt,
   26.22 + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
   26.23 + files located at the root of the source distribution.
   26.24 + These files may also be found in the public source
   26.25 + code repository located at:
   26.26 +        http://github.com/signal11/hidapi .
   26.27 +********************************************************/
   26.28 +
   26.29 +#ifndef _GNU_SOURCE
   26.30 +#define _GNU_SOURCE /* needed for wcsdup() before glibc 2.10 */
   26.31 +#endif
   26.32 +
   26.33 +/* C */
   26.34 +#include <stdio.h>
   26.35 +#include <string.h>
   26.36 +#include <stdlib.h>
   26.37 +#include <ctype.h>
   26.38 +#include <locale.h>
   26.39 +#include <errno.h>
   26.40 +
   26.41 +/* Unix */
   26.42 +#include <unistd.h>
   26.43 +#include <sys/types.h>
   26.44 +#include <sys/stat.h>
   26.45 +#include <sys/ioctl.h>
   26.46 +#include <sys/utsname.h>
   26.47 +#include <fcntl.h>
   26.48 +#include <pthread.h>
   26.49 +#include <wchar.h>
   26.50 +
   26.51 +/* GNU / LibUSB */
   26.52 +#include <libusb.h>
   26.53 +#ifndef __ANDROID__
   26.54 +#include <iconv.h>
   26.55 +#endif
   26.56 +
   26.57 +#include "hidapi.h"
   26.58 +
   26.59 +#ifdef NAMESPACE
   26.60 +namespace NAMESPACE
   26.61 +{
   26.62 +#endif
   26.63 +
   26.64 +#ifdef __ANDROID__
   26.65 +
   26.66 +/* Barrier implementation because Android/Bionic don't have pthread_barrier.
   26.67 +   This implementation came from Brent Priddy and was posted on
   26.68 +   StackOverflow. It is used with his permission. */
   26.69 +typedef int pthread_barrierattr_t;
   26.70 +typedef struct pthread_barrier {
   26.71 +    pthread_mutex_t mutex;
   26.72 +    pthread_cond_t cond;
   26.73 +    int count;
   26.74 +    int trip_count;
   26.75 +} pthread_barrier_t;
   26.76 +
   26.77 +static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
   26.78 +{
   26.79 +	if(count == 0) {
   26.80 +		errno = EINVAL;
   26.81 +		return -1;
   26.82 +	}
   26.83 +
   26.84 +	if(pthread_mutex_init(&barrier->mutex, 0) < 0) {
   26.85 +		return -1;
   26.86 +	}
   26.87 +	if(pthread_cond_init(&barrier->cond, 0) < 0) {
   26.88 +		pthread_mutex_destroy(&barrier->mutex);
   26.89 +		return -1;
   26.90 +	}
   26.91 +	barrier->trip_count = count;
   26.92 +	barrier->count = 0;
   26.93 +
   26.94 +	return 0;
   26.95 +}
   26.96 +
   26.97 +static int pthread_barrier_destroy(pthread_barrier_t *barrier)
   26.98 +{
   26.99 +	pthread_cond_destroy(&barrier->cond);
  26.100 +	pthread_mutex_destroy(&barrier->mutex);
  26.101 +	return 0;
  26.102 +}
  26.103 +
  26.104 +static int pthread_barrier_wait(pthread_barrier_t *barrier)
  26.105 +{
  26.106 +	pthread_mutex_lock(&barrier->mutex);
  26.107 +	++(barrier->count);
  26.108 +	if(barrier->count >= barrier->trip_count)
  26.109 +	{
  26.110 +		barrier->count = 0;
  26.111 +		pthread_cond_broadcast(&barrier->cond);
  26.112 +		pthread_mutex_unlock(&barrier->mutex);
  26.113 +		return 1;
  26.114 +	}
  26.115 +	else
  26.116 +	{
  26.117 +		pthread_cond_wait(&barrier->cond, &(barrier->mutex));
  26.118 +		pthread_mutex_unlock(&barrier->mutex);
  26.119 +		return 0;
  26.120 +	}
  26.121 +}
  26.122 +
  26.123 +#endif
  26.124 +
  26.125 +#if defined(__cplusplus) && !defined(NAMESPACE)
  26.126 +extern "C" {
  26.127 +#endif
  26.128 +
  26.129 +#ifdef DEBUG_PRINTF
  26.130 +#define LOG(...) fprintf(stderr, __VA_ARGS__)
  26.131 +#else
  26.132 +#define LOG(...) do {} while (0)
  26.133 +#endif
  26.134 +
  26.135 +#ifndef __FreeBSD__
  26.136 +#define DETACH_KERNEL_DRIVER
  26.137 +#endif
  26.138 +
  26.139 +/* Uncomment to enable the retrieval of Usage and Usage Page in
  26.140 +hid_enumerate(). Warning, on platforms different from FreeBSD
  26.141 +this is very invasive as it requires the detach
  26.142 +and re-attach of the kernel driver. See comments inside hid_enumerate().
  26.143 +libusb HIDAPI programs are encouraged to use the interface number
  26.144 +instead to differentiate between interfaces on a composite HID device. */
  26.145 +/*#define INVASIVE_GET_USAGE*/
  26.146 +
  26.147 +/* Linked List of input reports received from the device. */
  26.148 +struct input_report {
  26.149 +	uint8_t *data;
  26.150 +	size_t len;
  26.151 +	struct input_report *next;
  26.152 +};
  26.153 +
  26.154 +
  26.155 +struct hid_device_ {
  26.156 +	/* Handle to the actual device. */
  26.157 +	libusb_device_handle *device_handle;
  26.158 +
  26.159 +	/* Endpoint information */
  26.160 +	int input_endpoint;
  26.161 +	int output_endpoint;
  26.162 +	int input_ep_max_packet_size;
  26.163 +
  26.164 +	/* The interface number of the HID */
  26.165 +	int interface;
  26.166 +
  26.167 +	/* Indexes of Strings */
  26.168 +	int manufacturer_index;
  26.169 +	int product_index;
  26.170 +	int serial_index;
  26.171 +
  26.172 +	/* Whether blocking reads are used */
  26.173 +	int blocking; /* boolean */
  26.174 +
  26.175 +	/* Read thread objects */
  26.176 +	pthread_t thread;
  26.177 +	pthread_mutex_t mutex; /* Protects input_reports */
  26.178 +	pthread_cond_t condition;
  26.179 +	pthread_barrier_t barrier; /* Ensures correct startup sequence */
  26.180 +	int shutdown_thread;
  26.181 +	int cancelled;
  26.182 +	struct libusb_transfer *transfer;
  26.183 +
  26.184 +	/* List of received input reports. */
  26.185 +	struct input_report *input_reports;
  26.186 +};
  26.187 +
  26.188 +static libusb_context *usb_context = NULL;
  26.189 +
  26.190 +uint16_t get_usb_code_for_current_locale(void);
  26.191 +static int return_data(hid_device *dev, unsigned char *data, size_t length);
  26.192 +
  26.193 +static hid_device *new_hid_device(void)
  26.194 +{
  26.195 +	hid_device *dev = (hid_device *)calloc(1, sizeof(hid_device));
  26.196 +	dev->blocking = 1;
  26.197 +
  26.198 +	pthread_mutex_init(&dev->mutex, NULL);
  26.199 +	pthread_cond_init(&dev->condition, NULL);
  26.200 +	pthread_barrier_init(&dev->barrier, NULL, 2);
  26.201 +
  26.202 +	return dev;
  26.203 +}
  26.204 +
  26.205 +static void free_hid_device(hid_device *dev)
  26.206 +{
  26.207 +	/* Clean up the thread objects */
  26.208 +	pthread_barrier_destroy(&dev->barrier);
  26.209 +	pthread_cond_destroy(&dev->condition);
  26.210 +	pthread_mutex_destroy(&dev->mutex);
  26.211 +
  26.212 +	/* Free the device itself */
  26.213 +	free(dev);
  26.214 +}
  26.215 +
  26.216 +#if 0
  26.217 +/*TODO: Implement this funciton on hidapi/libusb.. */
  26.218 +static void register_error(hid_device *device, const char *op)
  26.219 +{
  26.220 +
  26.221 +}
  26.222 +#endif
  26.223 +
  26.224 +#ifdef INVASIVE_GET_USAGE
  26.225 +/* Get bytes from a HID Report Descriptor.
  26.226 +   Only call with a num_bytes of 0, 1, 2, or 4. */
  26.227 +static uint32_t get_bytes(uint8_t *rpt, size_t len, size_t num_bytes, size_t cur)
  26.228 +{
  26.229 +	/* Return if there aren't enough bytes. */
  26.230 +	if (cur + num_bytes >= len)
  26.231 +		return 0;
  26.232 +
  26.233 +	if (num_bytes == 0)
  26.234 +		return 0;
  26.235 +	else if (num_bytes == 1) {
  26.236 +		return rpt[cur+1];
  26.237 +	}
  26.238 +	else if (num_bytes == 2) {
  26.239 +		return (rpt[cur+2] * 256 + rpt[cur+1]);
  26.240 +	}
  26.241 +	else if (num_bytes == 4) {
  26.242 +		return (rpt[cur+4] * 0x01000000 +
  26.243 +		        rpt[cur+3] * 0x00010000 +
  26.244 +		        rpt[cur+2] * 0x00000100 +
  26.245 +		        rpt[cur+1] * 0x00000001);
  26.246 +	}
  26.247 +	else
  26.248 +		return 0;
  26.249 +}
  26.250 +
  26.251 +/* Retrieves the device's Usage Page and Usage from the report
  26.252 +   descriptor. The algorithm is simple, as it just returns the first
  26.253 +   Usage and Usage Page that it finds in the descriptor.
  26.254 +   The return value is 0 on success and -1 on failure. */
  26.255 +static int get_usage(uint8_t *report_descriptor, size_t size,
  26.256 +                     unsigned short *usage_page, unsigned short *usage)
  26.257 +{
  26.258 +	unsigned int i = 0;
  26.259 +	int size_code;
  26.260 +	int data_len, key_size;
  26.261 +	int usage_found = 0, usage_page_found = 0;
  26.262 +
  26.263 +	while (i < size) {
  26.264 +		int key = report_descriptor[i];
  26.265 +		int key_cmd = key & 0xfc;
  26.266 +
  26.267 +		//printf("key: %02hhx\n", key);
  26.268 +
  26.269 +		if ((key & 0xf0) == 0xf0) {
  26.270 +			/* This is a Long Item. The next byte contains the
  26.271 +			   length of the data section (value) for this key.
  26.272 +			   See the HID specification, version 1.11, section
  26.273 +			   6.2.2.3, titled "Long Items." */
  26.274 +			if (i+1 < size)
  26.275 +				data_len = report_descriptor[i+1];
  26.276 +			else
  26.277 +				data_len = 0; /* malformed report */
  26.278 +			key_size = 3;
  26.279 +		}
  26.280 +		else {
  26.281 +			/* This is a Short Item. The bottom two bits of the
  26.282 +			   key contain the size code for the data section
  26.283 +			   (value) for this key.  Refer to the HID
  26.284 +			   specification, version 1.11, section 6.2.2.2,
  26.285 +			   titled "Short Items." */
  26.286 +			size_code = key & 0x3;
  26.287 +			switch (size_code) {
  26.288 +			case 0:
  26.289 +			case 1:
  26.290 +			case 2:
  26.291 +				data_len = size_code;
  26.292 +				break;
  26.293 +			case 3:
  26.294 +				data_len = 4;
  26.295 +				break;
  26.296 +			default:
  26.297 +				/* Can't ever happen since size_code is & 0x3 */
  26.298 +				data_len = 0;
  26.299 +				break;
  26.300 +			};
  26.301 +			key_size = 1;
  26.302 +		}
  26.303 +
  26.304 +		if (key_cmd == 0x4) {
  26.305 +			*usage_page  = get_bytes(report_descriptor, size, data_len, i);
  26.306 +			usage_page_found = 1;
  26.307 +			//printf("Usage Page: %x\n", (uint32_t)*usage_page);
  26.308 +		}
  26.309 +		if (key_cmd == 0x8) {
  26.310 +			*usage = get_bytes(report_descriptor, size, data_len, i);
  26.311 +			usage_found = 1;
  26.312 +			//printf("Usage: %x\n", (uint32_t)*usage);
  26.313 +		}
  26.314 +
  26.315 +		if (usage_page_found && usage_found)
  26.316 +			return 0; /* success */
  26.317 +
  26.318 +		/* Skip over this key and it's associated data */
  26.319 +		i += data_len + key_size;
  26.320 +	}
  26.321 +
  26.322 +	return -1; /* failure */
  26.323 +}
  26.324 +#endif /* INVASIVE_GET_USAGE */
  26.325 +
  26.326 +#if defined(__FreeBSD__) && __FreeBSD__ < 10
  26.327 +/* The libusb version included in FreeBSD < 10 doesn't have this function. In
  26.328 +   mainline libusb, it's inlined in libusb.h. This function will bear a striking
  26.329 +   resemblance to that one, because there's about one way to code it.
  26.330 +
  26.331 +   Note that the data parameter is Unicode in UTF-16LE encoding.
  26.332 +   Return value is the number of bytes in data, or LIBUSB_ERROR_*.
  26.333 + */
  26.334 +static inline int libusb_get_string_descriptor(libusb_device_handle *dev,
  26.335 +	uint8_t descriptor_index, uint16_t lang_id,
  26.336 +	unsigned char *data, int length)
  26.337 +{
  26.338 +	return libusb_control_transfer(dev,
  26.339 +		LIBUSB_ENDPOINT_IN | 0x0, /* Endpoint 0 IN */
  26.340 +		LIBUSB_REQUEST_GET_DESCRIPTOR,
  26.341 +		(LIBUSB_DT_STRING << 8) | descriptor_index,
  26.342 +		lang_id, data, (uint16_t) length, 1000);
  26.343 +}
  26.344 +
  26.345 +#endif
  26.346 +
  26.347 +
  26.348 +/* Get the first language the device says it reports. This comes from
  26.349 +   USB string #0. */
  26.350 +static uint16_t get_first_language(libusb_device_handle *dev)
  26.351 +{
  26.352 +	uint16_t buf[32];
  26.353 +	int len;
  26.354 +
  26.355 +	/* Get the string from libusb. */
  26.356 +	len = libusb_get_string_descriptor(dev,
  26.357 +			0x0, /* String ID */
  26.358 +			0x0, /* Language */
  26.359 +			(unsigned char*)buf,
  26.360 +			sizeof(buf));
  26.361 +	if (len < 4)
  26.362 +		return 0x0;
  26.363 +
  26.364 +	return buf[1]; /* First two bytes are len and descriptor type. */
  26.365 +}
  26.366 +
  26.367 +static int is_language_supported(libusb_device_handle *dev, uint16_t lang)
  26.368 +{
  26.369 +	uint16_t buf[32];
  26.370 +	int len;
  26.371 +	int i;
  26.372 +
  26.373 +	/* Get the string from libusb. */
  26.374 +	len = libusb_get_string_descriptor(dev,
  26.375 +			0x0, /* String ID */
  26.376 +			0x0, /* Language */
  26.377 +			(unsigned char*)buf,
  26.378 +			sizeof(buf));
  26.379 +	if (len < 4)
  26.380 +		return 0x0;
  26.381 +
  26.382 +
  26.383 +	len /= 2; /* language IDs are two-bytes each. */
  26.384 +	/* Start at index 1 because there are two bytes of protocol data. */
  26.385 +	for (i = 1; i < len; i++) {
  26.386 +		if (buf[i] == lang)
  26.387 +			return 1;
  26.388 +	}
  26.389 +
  26.390 +	return 0;
  26.391 +}
  26.392 +
  26.393 +
  26.394 +/* This function returns a newly allocated wide string containing the USB
  26.395 +   device string numbered by the index. The returned string must be freed
  26.396 +   by using free(). */
  26.397 +static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx)
  26.398 +{
  26.399 +	char buf[512];
  26.400 +	int len;
  26.401 +	wchar_t *str = NULL;
  26.402 +
  26.403 +#ifndef __ANDROID__ /* we don't use iconv on Android */
  26.404 +	wchar_t wbuf[256];
  26.405 +	/* iconv variables */
  26.406 +	iconv_t ic;
  26.407 +	size_t inbytes;
  26.408 +	size_t outbytes;
  26.409 +	size_t res;
  26.410 +#ifdef __FreeBSD__
  26.411 +	const char *inptr;
  26.412 +#else
  26.413 +	char *inptr;
  26.414 +#endif
  26.415 +	char *outptr;
  26.416 +#endif
  26.417 +
  26.418 +	/* Determine which language to use. */
  26.419 +	uint16_t lang;
  26.420 +	lang = get_usb_code_for_current_locale();
  26.421 +	if (!is_language_supported(dev, lang))
  26.422 +		lang = get_first_language(dev);
  26.423 +
  26.424 +	/* Get the string from libusb. */
  26.425 +	len = libusb_get_string_descriptor(dev,
  26.426 +			idx,
  26.427 +			lang,
  26.428 +			(unsigned char*)buf,
  26.429 +			sizeof(buf));
  26.430 +	if (len < 0)
  26.431 +		return NULL;
  26.432 +
  26.433 +#ifdef __ANDROID__
  26.434 +
  26.435 +	/* Bionic does not have iconv support nor wcsdup() function, so it
  26.436 +	   has to be done manually.  The following code will only work for
  26.437 +	   code points that can be represented as a single UTF-16 character,
  26.438 +	   and will incorrectly convert any code points which require more
  26.439 +	   than one UTF-16 character.
  26.440 +
  26.441 +	   Skip over the first character (2-bytes).  */
  26.442 +	len -= 2;
  26.443 +	str = malloc((len / 2 + 1) * sizeof(wchar_t));
  26.444 +	int i;
  26.445 +	for (i = 0; i < len / 2; i++) {
  26.446 +		str[i] = buf[i * 2 + 2] | (buf[i * 2 + 3] << 8);
  26.447 +	}
  26.448 +	str[len / 2] = 0x00000000;
  26.449 +
  26.450 +#else
  26.451 +
  26.452 +	/* buf does not need to be explicitly NULL-terminated because
  26.453 +	   it is only passed into iconv() which does not need it. */
  26.454 +
  26.455 +	/* Initialize iconv. */
  26.456 +	ic = iconv_open("WCHAR_T", "UTF-16LE");
  26.457 +	if (ic == (iconv_t)-1) {
  26.458 +		LOG("iconv_open() failed\n");
  26.459 +		return NULL;
  26.460 +	}
  26.461 +
  26.462 +	/* Convert to native wchar_t (UTF-32 on glibc/BSD systems).
  26.463 +	   Skip the first character (2-bytes). */
  26.464 +	inptr = buf+2;
  26.465 +	inbytes = len-2;
  26.466 +	outptr = (char*) wbuf;
  26.467 +	outbytes = sizeof(wbuf);
  26.468 +	res = iconv(ic, &inptr, &inbytes, &outptr, &outbytes);
  26.469 +	if (res == (size_t)-1) {
  26.470 +		LOG("iconv() failed\n");
  26.471 +		goto err;
  26.472 +	}
  26.473 +
  26.474 +	/* Write the terminating NULL. */
  26.475 +	wbuf[sizeof(wbuf)/sizeof(wbuf[0])-1] = 0x00000000;
  26.476 +	if (outbytes >= sizeof(wbuf[0]))
  26.477 +		*((wchar_t*)outptr) = 0x00000000;
  26.478 +
  26.479 +	/* Allocate and copy the string. */
  26.480 +	str = wcsdup(wbuf);
  26.481 +
  26.482 +err:
  26.483 +	iconv_close(ic);
  26.484 +
  26.485 +#endif
  26.486 +
  26.487 +	return str;
  26.488 +}
  26.489 +
  26.490 +static char *make_path(libusb_device *dev, int interface_number)
  26.491 +{
  26.492 +	char str[64];
  26.493 +	snprintf(str, sizeof(str), "%04x:%04x:%02x",
  26.494 +		libusb_get_bus_number(dev),
  26.495 +		libusb_get_device_address(dev),
  26.496 +		interface_number);
  26.497 +	str[sizeof(str)-1] = '\0';
  26.498 +
  26.499 +	return strdup(str);
  26.500 +}
  26.501 +
  26.502 +
  26.503 +int HID_API_EXPORT hid_init(void)
  26.504 +{
  26.505 +	if (!usb_context) {
  26.506 +		const char *locale;
  26.507 +
  26.508 +		/* Init Libusb */
  26.509 +		if (libusb_init(&usb_context))
  26.510 +			return -1;
  26.511 +
  26.512 +		/* Set the locale if it's not set. */
  26.513 +		locale = setlocale(LC_CTYPE, NULL);
  26.514 +		if (!locale)
  26.515 +			setlocale(LC_CTYPE, "");
  26.516 +	}
  26.517 +
  26.518 +	return 0;
  26.519 +}
  26.520 +
  26.521 +int HID_API_EXPORT hid_exit(void)
  26.522 +{
  26.523 +	if (usb_context) {
  26.524 +		libusb_exit(usb_context);
  26.525 +		usb_context = NULL;
  26.526 +	}
  26.527 +
  26.528 +	return 0;
  26.529 +}
  26.530 +
  26.531 +static int is_xbox360(unsigned short vendor_id, const struct libusb_interface_descriptor *intf_desc)
  26.532 +{
  26.533 +	static const int XB360_IFACE_SUBCLASS = 93;
  26.534 +	static const int XB360_IFACE_PROTOCOL = 1; /* Wired only */
  26.535 +	static const int SUPPORTED_VENDORS[] = {
  26.536 +		0x0079, /* GPD Win 2 */
  26.537 +		0x044f, /* Thrustmaster */
  26.538 +		0x045e, /* Microsoft */
  26.539 +		0x046d, /* Logitech */
  26.540 +		0x056e, /* Elecom */
  26.541 +		0x06a3, /* Saitek */
  26.542 +		0x0738, /* Mad Catz */
  26.543 +		0x07ff, /* Mad Catz */
  26.544 +		0x0e6f, /* Unknown */
  26.545 +		0x0f0d, /* Hori */
  26.546 +		0x11c9, /* Nacon */
  26.547 +		0x12ab, /* Unknown */
  26.548 +		0x1430, /* RedOctane */
  26.549 +		0x146b, /* BigBen */
  26.550 +		0x1532, /* Razer Sabertooth */
  26.551 +		0x15e4, /* Numark */
  26.552 +		0x162e, /* Joytech */
  26.553 +		0x1689, /* Razer Onza */
  26.554 +		0x1bad, /* Harmonix */
  26.555 +		0x24c6, /* PowerA */
  26.556 +	};
  26.557 +
  26.558 +	if (intf_desc->bInterfaceNumber == 0 &&
  26.559 +	    intf_desc->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC &&
  26.560 +	    intf_desc->bInterfaceSubClass == XB360_IFACE_SUBCLASS &&
  26.561 +	    intf_desc->bInterfaceProtocol == XB360_IFACE_PROTOCOL) {
  26.562 +		int i;
  26.563 +		for (i = 0; i < sizeof(SUPPORTED_VENDORS)/sizeof(SUPPORTED_VENDORS[0]); ++i) {
  26.564 +			if (vendor_id == SUPPORTED_VENDORS[i]) {
  26.565 +				return 1;
  26.566 +			}
  26.567 +		}
  26.568 +	}
  26.569 +	return 0;
  26.570 +}
  26.571 +
  26.572 +static int is_xboxone(unsigned short vendor_id, const struct libusb_interface_descriptor *intf_desc)
  26.573 +{
  26.574 +        static const int XB1_IFACE_SUBCLASS = 71;
  26.575 +        static const int XB1_IFACE_PROTOCOL = 208;
  26.576 +        static const int SUPPORTED_VENDORS[] = {
  26.577 +            0x045e, /* Microsoft */
  26.578 +            0x0738, /* Mad Catz */
  26.579 +            0x0e6f, /* Unknown */
  26.580 +            0x0f0d, /* Hori */
  26.581 +            0x1532, /* Razer Wildcat */
  26.582 +            0x24c6, /* PowerA */
  26.583 +        };
  26.584 +
  26.585 +	if (intf_desc->bInterfaceNumber == 0 &&
  26.586 +	    intf_desc->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC &&
  26.587 +	    intf_desc->bInterfaceSubClass == XB1_IFACE_SUBCLASS &&
  26.588 +	    intf_desc->bInterfaceProtocol == XB1_IFACE_PROTOCOL) {
  26.589 +		int i;
  26.590 +		for (i = 0; i < sizeof(SUPPORTED_VENDORS)/sizeof(SUPPORTED_VENDORS[0]); ++i) {
  26.591 +			if (vendor_id == SUPPORTED_VENDORS[i]) {
  26.592 +				return 1;
  26.593 +			}
  26.594 +		}
  26.595 +	}
  26.596 +	return 0;
  26.597 +}
  26.598 +
  26.599 +static int should_enumerate_interface(unsigned short vendor_id, const struct libusb_interface_descriptor *intf_desc)
  26.600 +{
  26.601 +	if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID)
  26.602 +		return 1;
  26.603 +
  26.604 +	/* Also enumerate Xbox 360 controllers */
  26.605 +	if (is_xbox360(vendor_id, intf_desc))
  26.606 +	{
  26.607 +		/* hid_write() to Xbox 360 controllers doesn't seem to work on Linux:
  26.608 +		   - xpad 1-2:1.0: xpad_try_sending_next_out_packet - usb_submit_urb failed with result -2
  26.609 +		   Xbox 360 controller support is good on Linux anyway, so we'll ignore this for now.
  26.610 +		return 1;
  26.611 +		*/
  26.612 +	}
  26.613 +
  26.614 +	/* Also enumerate Xbox One controllers */
  26.615 +	if (is_xboxone(vendor_id, intf_desc))
  26.616 +		return 1;
  26.617 +
  26.618 +	return 0;
  26.619 +}
  26.620 +
  26.621 +struct hid_device_info  HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
  26.622 +{
  26.623 +	libusb_device **devs;
  26.624 +	libusb_device *dev;
  26.625 +	libusb_device_handle *handle;
  26.626 +	ssize_t num_devs;
  26.627 +	int i = 0;
  26.628 +
  26.629 +	struct hid_device_info *root = NULL; /* return object */
  26.630 +	struct hid_device_info *cur_dev = NULL;
  26.631 +
  26.632 +	if(hid_init() < 0)
  26.633 +		return NULL;
  26.634 +
  26.635 +	num_devs = libusb_get_device_list(usb_context, &devs);
  26.636 +	if (num_devs < 0)
  26.637 +		return NULL;
  26.638 +	while ((dev = devs[i++]) != NULL) {
  26.639 +		struct libusb_device_descriptor desc;
  26.640 +		struct libusb_config_descriptor *conf_desc = NULL;
  26.641 +		int j, k;
  26.642 +		int interface_num = 0;
  26.643 +
  26.644 +		int res = libusb_get_device_descriptor(dev, &desc);
  26.645 +		unsigned short dev_vid = desc.idVendor;
  26.646 +		unsigned short dev_pid = desc.idProduct;
  26.647 +
  26.648 +		res = libusb_get_active_config_descriptor(dev, &conf_desc);
  26.649 +		if (res < 0)
  26.650 +			libusb_get_config_descriptor(dev, 0, &conf_desc);
  26.651 +		if (conf_desc) {
  26.652 +			for (j = 0; j < conf_desc->bNumInterfaces; j++) {
  26.653 +				const struct libusb_interface *intf = &conf_desc->interface[j];
  26.654 +				for (k = 0; k < intf->num_altsetting; k++) {
  26.655 +					const struct libusb_interface_descriptor *intf_desc;
  26.656 +					intf_desc = &intf->altsetting[k];
  26.657 +					if (should_enumerate_interface(dev_vid, intf_desc)) {
  26.658 +						interface_num = intf_desc->bInterfaceNumber;
  26.659 +
  26.660 +						/* Check the VID/PID against the arguments */
  26.661 +						if ((vendor_id == 0x0 || vendor_id == dev_vid) &&
  26.662 +						    (product_id == 0x0 || product_id == dev_pid)) {
  26.663 +							struct hid_device_info *tmp;
  26.664 +
  26.665 +							/* VID/PID match. Create the record. */
  26.666 +							tmp = (struct hid_device_info *)calloc(1, sizeof(struct hid_device_info));
  26.667 +							if (cur_dev) {
  26.668 +								cur_dev->next = tmp;
  26.669 +							}
  26.670 +							else {
  26.671 +								root = tmp;
  26.672 +							}
  26.673 +							cur_dev = tmp;
  26.674 +
  26.675 +							/* Fill out the record */
  26.676 +							cur_dev->next = NULL;
  26.677 +							cur_dev->path = make_path(dev, interface_num);
  26.678 +
  26.679 +							res = libusb_open(dev, &handle);
  26.680 +
  26.681 +							if (res >= 0) {
  26.682 +								/* Serial Number */
  26.683 +								if (desc.iSerialNumber > 0)
  26.684 +									cur_dev->serial_number =
  26.685 +										get_usb_string(handle, desc.iSerialNumber);
  26.686 +
  26.687 +								/* Manufacturer and Product strings */
  26.688 +								if (desc.iManufacturer > 0)
  26.689 +									cur_dev->manufacturer_string =
  26.690 +										get_usb_string(handle, desc.iManufacturer);
  26.691 +								if (desc.iProduct > 0)
  26.692 +									cur_dev->product_string =
  26.693 +										get_usb_string(handle, desc.iProduct);
  26.694 +
  26.695 +#ifdef INVASIVE_GET_USAGE
  26.696 +{
  26.697 +							/*
  26.698 +							This section is removed because it is too
  26.699 +							invasive on the system. Getting a Usage Page
  26.700 +							and Usage requires parsing the HID Report
  26.701 +							descriptor. Getting a HID Report descriptor
  26.702 +							involves claiming the interface. Claiming the
  26.703 +							interface involves detaching the kernel driver.
  26.704 +							Detaching the kernel driver is hard on the system
  26.705 +							because it will unclaim interfaces (if another
  26.706 +							app has them claimed) and the re-attachment of
  26.707 +							the driver will sometimes change /dev entry names.
  26.708 +							It is for these reasons that this section is
  26.709 +							#if 0. For composite devices, use the interface
  26.710 +							field in the hid_device_info struct to distinguish
  26.711 +							between interfaces. */
  26.712 +								unsigned char data[256];
  26.713 +#ifdef DETACH_KERNEL_DRIVER
  26.714 +								int detached = 0;
  26.715 +								/* Usage Page and Usage */
  26.716 +								res = libusb_kernel_driver_active(handle, interface_num);
  26.717 +								if (res == 1) {
  26.718 +									res = libusb_detach_kernel_driver(handle, interface_num);
  26.719 +									if (res < 0)
  26.720 +										LOG("Couldn't detach kernel driver, even though a kernel driver was attached.");
  26.721 +									else
  26.722 +										detached = 1;
  26.723 +								}
  26.724 +#endif
  26.725 +								res = libusb_claim_interface(handle, interface_num);
  26.726 +								if (res >= 0) {
  26.727 +									/* Get the HID Report Descriptor. */
  26.728 +									res = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_INTERFACE, LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_REPORT << 8)|interface_num, 0, data, sizeof(data), 5000);
  26.729 +									if (res >= 0) {
  26.730 +										unsigned short page=0, usage=0;
  26.731 +										/* Parse the usage and usage page
  26.732 +										   out of the report descriptor. */
  26.733 +										get_usage(data, res,  &page, &usage);
  26.734 +										cur_dev->usage_page = page;
  26.735 +										cur_dev->usage = usage;
  26.736 +									}
  26.737 +									else
  26.738 +										LOG("libusb_control_transfer() for getting the HID report failed with %d\n", res);
  26.739 +
  26.740 +									/* Release the interface */
  26.741 +									res = libusb_release_interface(handle, interface_num);
  26.742 +									if (res < 0)
  26.743 +										LOG("Can't release the interface.\n");
  26.744 +								}
  26.745 +								else
  26.746 +									LOG("Can't claim interface %d\n", res);
  26.747 +#ifdef DETACH_KERNEL_DRIVER
  26.748 +								/* Re-attach kernel driver if necessary. */
  26.749 +								if (detached) {
  26.750 +									res = libusb_attach_kernel_driver(handle, interface_num);
  26.751 +									if (res < 0)
  26.752 +										LOG("Couldn't re-attach kernel driver.\n");
  26.753 +								}
  26.754 +#endif
  26.755 +}
  26.756 +#endif /* INVASIVE_GET_USAGE */
  26.757 +
  26.758 +								libusb_close(handle);
  26.759 +							}
  26.760 +							/* VID/PID */
  26.761 +							cur_dev->vendor_id = dev_vid;
  26.762 +							cur_dev->product_id = dev_pid;
  26.763 +
  26.764 +							/* Release Number */
  26.765 +							cur_dev->release_number = desc.bcdDevice;
  26.766 +
  26.767 +							/* Interface Number */
  26.768 +							cur_dev->interface_number = interface_num;
  26.769 +						}
  26.770 +					}
  26.771 +				} /* altsettings */
  26.772 +			} /* interfaces */
  26.773 +			libusb_free_config_descriptor(conf_desc);
  26.774 +		}
  26.775 +	}
  26.776 +
  26.777 +	libusb_free_device_list(devs, 1);
  26.778 +
  26.779 +	return root;
  26.780 +}
  26.781 +
  26.782 +void  HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
  26.783 +{
  26.784 +	struct hid_device_info *d = devs;
  26.785 +	while (d) {
  26.786 +		struct hid_device_info *next = d->next;
  26.787 +		free(d->path);
  26.788 +		free(d->serial_number);
  26.789 +		free(d->manufacturer_string);
  26.790 +		free(d->product_string);
  26.791 +		free(d);
  26.792 +		d = next;
  26.793 +	}
  26.794 +}
  26.795 +
  26.796 +hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
  26.797 +{
  26.798 +	struct hid_device_info *devs, *cur_dev;
  26.799 +	const char *path_to_open = NULL;
  26.800 +	hid_device *handle = NULL;
  26.801 +
  26.802 +	devs = hid_enumerate(vendor_id, product_id);
  26.803 +	cur_dev = devs;
  26.804 +	while (cur_dev) {
  26.805 +		if (cur_dev->vendor_id == vendor_id &&
  26.806 +		    cur_dev->product_id == product_id) {
  26.807 +			if (serial_number) {
  26.808 +				if (cur_dev->serial_number &&
  26.809 +				    wcscmp(serial_number, cur_dev->serial_number) == 0) {
  26.810 +					path_to_open = cur_dev->path;
  26.811 +					break;
  26.812 +				}
  26.813 +			}
  26.814 +			else {
  26.815 +				path_to_open = cur_dev->path;
  26.816 +				break;
  26.817 +			}
  26.818 +		}
  26.819 +		cur_dev = cur_dev->next;
  26.820 +	}
  26.821 +
  26.822 +	if (path_to_open) {
  26.823 +		/* Open the device */
  26.824 +		handle = hid_open_path(path_to_open, 0);
  26.825 +	}
  26.826 +
  26.827 +	hid_free_enumeration(devs);
  26.828 +
  26.829 +	return handle;
  26.830 +}
  26.831 +
  26.832 +static void read_callback(struct libusb_transfer *transfer)
  26.833 +{
  26.834 +	hid_device *dev = (hid_device *)transfer->user_data;
  26.835 +	int res;
  26.836 +
  26.837 +	if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
  26.838 +
  26.839 +		struct input_report *rpt = (struct input_report *)malloc(sizeof(*rpt));
  26.840 +		rpt->data = (uint8_t *)malloc(transfer->actual_length);
  26.841 +		memcpy(rpt->data, transfer->buffer, transfer->actual_length);
  26.842 +		rpt->len = transfer->actual_length;
  26.843 +		rpt->next = NULL;
  26.844 +
  26.845 +		pthread_mutex_lock(&dev->mutex);
  26.846 +
  26.847 +		/* Attach the new report object to the end of the list. */
  26.848 +		if (dev->input_reports == NULL) {
  26.849 +			/* The list is empty. Put it at the root. */
  26.850 +			dev->input_reports = rpt;
  26.851 +			pthread_cond_signal(&dev->condition);
  26.852 +		}
  26.853 +		else {
  26.854 +			/* Find the end of the list and attach. */
  26.855 +			struct input_report *cur = dev->input_reports;
  26.856 +			int num_queued = 0;
  26.857 +			while (cur->next != NULL) {
  26.858 +				cur = cur->next;
  26.859 +				num_queued++;
  26.860 +			}
  26.861 +			cur->next = rpt;
  26.862 +
  26.863 +			/* Pop one off if we've reached 30 in the queue. This
  26.864 +			   way we don't grow forever if the user never reads
  26.865 +			   anything from the device. */
  26.866 +			if (num_queued > 30) {
  26.867 +				return_data(dev, NULL, 0);
  26.868 +			}
  26.869 +		}
  26.870 +		pthread_mutex_unlock(&dev->mutex);
  26.871 +	}
  26.872 +	else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
  26.873 +		dev->shutdown_thread = 1;
  26.874 +		dev->cancelled = 1;
  26.875 +		return;
  26.876 +	}
  26.877 +	else if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE) {
  26.878 +		dev->shutdown_thread = 1;
  26.879 +		dev->cancelled = 1;
  26.880 +		return;
  26.881 +	}
  26.882 +	else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) {
  26.883 +		//LOG("Timeout (normal)\n");
  26.884 +	}
  26.885 +	else {
  26.886 +		LOG("Unknown transfer code: %d\n", transfer->status);
  26.887 +	}
  26.888 +
  26.889 +	/* Re-submit the transfer object. */
  26.890 +	res = libusb_submit_transfer(transfer);
  26.891 +	if (res != 0) {
  26.892 +		LOG("Unable to submit URB. libusb error code: %d\n", res);
  26.893 +		dev->shutdown_thread = 1;
  26.894 +		dev->cancelled = 1;
  26.895 +	}
  26.896 +}
  26.897 +
  26.898 +
  26.899 +static void *read_thread(void *param)
  26.900 +{
  26.901 +	hid_device *dev = (hid_device *)param;
  26.902 +	unsigned char *buf;
  26.903 +	const size_t length = dev->input_ep_max_packet_size;
  26.904 +
  26.905 +	/* Set up the transfer object. */
  26.906 +	buf = (unsigned char *)malloc(length);
  26.907 +	dev->transfer = libusb_alloc_transfer(0);
  26.908 +	libusb_fill_interrupt_transfer(dev->transfer,
  26.909 +		dev->device_handle,
  26.910 +		dev->input_endpoint,
  26.911 +		buf,
  26.912 +		length,
  26.913 +		read_callback,
  26.914 +		dev,
  26.915 +		5000/*timeout*/);
  26.916 +
  26.917 +	/* Make the first submission. Further submissions are made
  26.918 +	   from inside read_callback() */
  26.919 +	libusb_submit_transfer(dev->transfer);
  26.920 +
  26.921 +	/* Notify the main thread that the read thread is up and running. */
  26.922 +	pthread_barrier_wait(&dev->barrier);
  26.923 +
  26.924 +	/* Handle all the events. */
  26.925 +	while (!dev->shutdown_thread) {
  26.926 +		int res;
  26.927 +		res = libusb_handle_events(usb_context);
  26.928 +		if (res < 0) {
  26.929 +			/* There was an error. */
  26.930 +			LOG("read_thread(): libusb reports error # %d\n", res);
  26.931 +
  26.932 +			/* Break out of this loop only on fatal error.*/
  26.933 +			if (res != LIBUSB_ERROR_BUSY &&
  26.934 +			    res != LIBUSB_ERROR_TIMEOUT &&
  26.935 +			    res != LIBUSB_ERROR_OVERFLOW &&
  26.936 +			    res != LIBUSB_ERROR_INTERRUPTED) {
  26.937 +				break;
  26.938 +			}
  26.939 +		}
  26.940 +	}
  26.941 +
  26.942 +	/* Cancel any transfer that may be pending. This call will fail
  26.943 +	   if no transfers are pending, but that's OK. */
  26.944 +	libusb_cancel_transfer(dev->transfer);
  26.945 +
  26.946 +	while (!dev->cancelled)
  26.947 +		libusb_handle_events_completed(usb_context, &dev->cancelled);
  26.948 +
  26.949 +	/* Now that the read thread is stopping, Wake any threads which are
  26.950 +	   waiting on data (in hid_read_timeout()). Do this under a mutex to
  26.951 +	   make sure that a thread which is about to go to sleep waiting on
  26.952 +	   the condition actually will go to sleep before the condition is
  26.953 +	   signaled. */
  26.954 +	pthread_mutex_lock(&dev->mutex);
  26.955 +	pthread_cond_broadcast(&dev->condition);
  26.956 +	pthread_mutex_unlock(&dev->mutex);
  26.957 +
  26.958 +	/* The dev->transfer->buffer and dev->transfer objects are cleaned up
  26.959 +	   in hid_close(). They are not cleaned up here because this thread
  26.960 +	   could end either due to a disconnect or due to a user
  26.961 +	   call to hid_close(). In both cases the objects can be safely
  26.962 +	   cleaned up after the call to pthread_join() (in hid_close()), but
  26.963 +	   since hid_close() calls libusb_cancel_transfer(), on these objects,
  26.964 +	   they can not be cleaned up here. */
  26.965 +
  26.966 +	return NULL;
  26.967 +}
  26.968 +
  26.969 +
  26.970 +hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
  26.971 +{
  26.972 +	hid_device *dev = NULL;
  26.973 +
  26.974 +	libusb_device **devs;
  26.975 +	libusb_device *usb_dev;
  26.976 +	int res;
  26.977 +	int d = 0;
  26.978 +	int good_open = 0;
  26.979 +
  26.980 +	if(hid_init() < 0)
  26.981 +		return NULL;
  26.982 +
  26.983 +	dev = new_hid_device();
  26.984 +
  26.985 +	libusb_get_device_list(usb_context, &devs);
  26.986 +	while ((usb_dev = devs[d++]) != NULL) {
  26.987 +		struct libusb_device_descriptor desc;
  26.988 +		struct libusb_config_descriptor *conf_desc = NULL;
  26.989 +		int i,j,k;
  26.990 +		libusb_get_device_descriptor(usb_dev, &desc);
  26.991 +
  26.992 +		if (libusb_get_active_config_descriptor(usb_dev, &conf_desc) < 0)
  26.993 +			continue;
  26.994 +		for (j = 0; j < conf_desc->bNumInterfaces; j++) {
  26.995 +			const struct libusb_interface *intf = &conf_desc->interface[j];
  26.996 +			for (k = 0; k < intf->num_altsetting; k++) {
  26.997 +				const struct libusb_interface_descriptor *intf_desc;
  26.998 +				intf_desc = &intf->altsetting[k];
  26.999 +				if (should_enumerate_interface(desc.idVendor, intf_desc)) {
 26.1000 +					char *dev_path = make_path(usb_dev, intf_desc->bInterfaceNumber);
 26.1001 +					if (!strcmp(dev_path, path)) {
 26.1002 +						/* Matched Paths. Open this device */
 26.1003 +
 26.1004 +						/* OPEN HERE */
 26.1005 +						res = libusb_open(usb_dev, &dev->device_handle);
 26.1006 +						if (res < 0) {
 26.1007 +							LOG("can't open device\n");
 26.1008 +							free(dev_path);
 26.1009 +							break;
 26.1010 +						}
 26.1011 +						good_open = 1;
 26.1012 +#ifdef DETACH_KERNEL_DRIVER
 26.1013 +						/* Detach the kernel driver, but only if the
 26.1014 +						   device is managed by the kernel */
 26.1015 +						if (libusb_kernel_driver_active(dev->device_handle, intf_desc->bInterfaceNumber) == 1) {
 26.1016 +							res = libusb_detach_kernel_driver(dev->device_handle, intf_desc->bInterfaceNumber);
 26.1017 +							if (res < 0) {
 26.1018 +								libusb_close(dev->device_handle);
 26.1019 +								LOG("Unable to detach Kernel Driver\n");
 26.1020 +								free(dev_path);
 26.1021 +								good_open = 0;
 26.1022 +								break;
 26.1023 +							}
 26.1024 +						}
 26.1025 +#endif
 26.1026 +						res = libusb_claim_interface(dev->device_handle, intf_desc->bInterfaceNumber);
 26.1027 +						if (res < 0) {
 26.1028 +							LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res);
 26.1029 +							free(dev_path);
 26.1030 +							libusb_close(dev->device_handle);
 26.1031 +							good_open = 0;
 26.1032 +							break;
 26.1033 +						}
 26.1034 +
 26.1035 +						/* Store off the string descriptor indexes */
 26.1036 +						dev->manufacturer_index = desc.iManufacturer;
 26.1037 +						dev->product_index      = desc.iProduct;
 26.1038 +						dev->serial_index       = desc.iSerialNumber;
 26.1039 +
 26.1040 +						/* Store off the interface number */
 26.1041 +						dev->interface = intf_desc->bInterfaceNumber;
 26.1042 +
 26.1043 +						/* Find the INPUT and OUTPUT endpoints. An
 26.1044 +						   OUTPUT endpoint is not required. */
 26.1045 +						for (i = 0; i < intf_desc->bNumEndpoints; i++) {
 26.1046 +							const struct libusb_endpoint_descriptor *ep
 26.1047 +								= &intf_desc->endpoint[i];
 26.1048 +
 26.1049 +							/* Determine the type and direction of this
 26.1050 +							   endpoint. */
 26.1051 +							int is_interrupt =
 26.1052 +								(ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK)
 26.1053 +							      == LIBUSB_TRANSFER_TYPE_INTERRUPT;
 26.1054 +							int is_output =
 26.1055 +								(ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
 26.1056 +							      == LIBUSB_ENDPOINT_OUT;
 26.1057 +							int is_input =
 26.1058 +								(ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
 26.1059 +							      == LIBUSB_ENDPOINT_IN;
 26.1060 +
 26.1061 +							/* Decide whether to use it for input or output. */
 26.1062 +							if (dev->input_endpoint == 0 &&
 26.1063 +							    is_interrupt && is_input) {
 26.1064 +								/* Use this endpoint for INPUT */
 26.1065 +								dev->input_endpoint = ep->bEndpointAddress;
 26.1066 +								dev->input_ep_max_packet_size = ep->wMaxPacketSize;
 26.1067 +							}
 26.1068 +							if (dev->output_endpoint == 0 &&
 26.1069 +							    is_interrupt && is_output) {
 26.1070 +								/* Use this endpoint for OUTPUT */
 26.1071 +								dev->output_endpoint = ep->bEndpointAddress;
 26.1072 +							}
 26.1073 +						}
 26.1074 +
 26.1075 +						pthread_create(&dev->thread, NULL, read_thread, dev);
 26.1076 +
 26.1077 +						/* Wait here for the read thread to be initialized. */
 26.1078 +						pthread_barrier_wait(&dev->barrier);
 26.1079 +
 26.1080 +					}
 26.1081 +					free(dev_path);
 26.1082 +				}
 26.1083 +			}
 26.1084 +		}
 26.1085 +		libusb_free_config_descriptor(conf_desc);
 26.1086 +
 26.1087 +	}
 26.1088 +
 26.1089 +	libusb_free_device_list(devs, 1);
 26.1090 +
 26.1091 +	/* If we have a good handle, return it. */
 26.1092 +	if (good_open) {
 26.1093 +		return dev;
 26.1094 +	}
 26.1095 +	else {
 26.1096 +		/* Unable to open any devices. */
 26.1097 +		free_hid_device(dev);
 26.1098 +		return NULL;
 26.1099 +	}
 26.1100 +}
 26.1101 +
 26.1102 +
 26.1103 +int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
 26.1104 +{
 26.1105 +	int res;
 26.1106 +	int report_number = data[0];
 26.1107 +	int skipped_report_id = 0;
 26.1108 +
 26.1109 +	if (report_number == 0x0) {
 26.1110 +		data++;
 26.1111 +		length--;
 26.1112 +		skipped_report_id = 1;
 26.1113 +	}
 26.1114 +
 26.1115 +
 26.1116 +	if (dev->output_endpoint <= 0) {
 26.1117 +		/* No interrupt out endpoint. Use the Control Endpoint */
 26.1118 +		res = libusb_control_transfer(dev->device_handle,
 26.1119 +			LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT,
 26.1120 +			0x09/*HID Set_Report*/,
 26.1121 +			(2/*HID output*/ << 8) | report_number,
 26.1122 +			dev->interface,
 26.1123 +			(unsigned char *)data, length,
 26.1124 +			1000/*timeout millis*/);
 26.1125 +
 26.1126 +		if (res < 0)
 26.1127 +			return -1;
 26.1128 +
 26.1129 +		if (skipped_report_id)
 26.1130 +			length++;
 26.1131 +
 26.1132 +		return length;
 26.1133 +	}
 26.1134 +	else {
 26.1135 +		/* Use the interrupt out endpoint */
 26.1136 +		int actual_length;
 26.1137 +		res = libusb_interrupt_transfer(dev->device_handle,
 26.1138 +			dev->output_endpoint,
 26.1139 +			(unsigned char*)data,
 26.1140 +			length,
 26.1141 +			&actual_length, 1000);
 26.1142 +
 26.1143 +		if (res < 0)
 26.1144 +			return -1;
 26.1145 +
 26.1146 +		if (skipped_report_id)
 26.1147 +			actual_length++;
 26.1148 +
 26.1149 +		return actual_length;
 26.1150 +	}
 26.1151 +}
 26.1152 +
 26.1153 +/* Helper function, to simplify hid_read().
 26.1154 +   This should be called with dev->mutex locked. */
 26.1155 +static int return_data(hid_device *dev, unsigned char *data, size_t length)
 26.1156 +{
 26.1157 +	/* Copy the data out of the linked list item (rpt) into the
 26.1158 +	   return buffer (data), and delete the liked list item. */
 26.1159 +	struct input_report *rpt = dev->input_reports;
 26.1160 +	size_t len = (length < rpt->len)? length: rpt->len;
 26.1161 +	if (data && len > 0)
 26.1162 +		memcpy(data, rpt->data, len);
 26.1163 +	dev->input_reports = rpt->next;
 26.1164 +	free(rpt->data);
 26.1165 +	free(rpt);
 26.1166 +	return len;
 26.1167 +}
 26.1168 +
 26.1169 +static void cleanup_mutex(void *param)
 26.1170 +{
 26.1171 +	hid_device *dev = (hid_device *)param;
 26.1172 +	pthread_mutex_unlock(&dev->mutex);
 26.1173 +}
 26.1174 +
 26.1175 +
 26.1176 +int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
 26.1177 +{
 26.1178 +	int bytes_read = -1;
 26.1179 +
 26.1180 +#if 0
 26.1181 +	int transferred;
 26.1182 +	int res = libusb_interrupt_transfer(dev->device_handle, dev->input_endpoint, data, length, &transferred, 5000);
 26.1183 +	LOG("transferred: %d\n", transferred);
 26.1184 +	return transferred;
 26.1185 +#endif
 26.1186 +
 26.1187 +	pthread_mutex_lock(&dev->mutex);
 26.1188 +	pthread_cleanup_push(&cleanup_mutex, dev);
 26.1189 +
 26.1190 +	/* There's an input report queued up. Return it. */
 26.1191 +	if (dev->input_reports) {
 26.1192 +		/* Return the first one */
 26.1193 +		bytes_read = return_data(dev, data, length);
 26.1194 +		goto ret;
 26.1195 +	}
 26.1196 +
 26.1197 +	if (dev->shutdown_thread) {
 26.1198 +		/* This means the device has been disconnected.
 26.1199 +		   An error code of -1 should be returned. */
 26.1200 +		bytes_read = -1;
 26.1201 +		goto ret;
 26.1202 +	}
 26.1203 +
 26.1204 +	if (milliseconds == -1) {
 26.1205 +		/* Blocking */
 26.1206 +		while (!dev->input_reports && !dev->shutdown_thread) {
 26.1207 +			pthread_cond_wait(&dev->condition, &dev->mutex);
 26.1208 +		}
 26.1209 +		if (dev->input_reports) {
 26.1210 +			bytes_read = return_data(dev, data, length);
 26.1211 +		}
 26.1212 +	}
 26.1213 +	else if (milliseconds > 0) {
 26.1214 +		/* Non-blocking, but called with timeout. */
 26.1215 +		int res;
 26.1216 +		struct timespec ts;
 26.1217 +		clock_gettime(CLOCK_REALTIME, &ts);
 26.1218 +		ts.tv_sec += milliseconds / 1000;
 26.1219 +		ts.tv_nsec += (milliseconds % 1000) * 1000000;
 26.1220 +		if (ts.tv_nsec >= 1000000000L) {
 26.1221 +			ts.tv_sec++;
 26.1222 +			ts.tv_nsec -= 1000000000L;
 26.1223 +		}
 26.1224 +
 26.1225 +		while (!dev->input_reports && !dev->shutdown_thread) {
 26.1226 +			res = pthread_cond_timedwait(&dev->condition, &dev->mutex, &ts);
 26.1227 +			if (res == 0) {
 26.1228 +				if (dev->input_reports) {
 26.1229 +					bytes_read = return_data(dev, data, length);
 26.1230 +					break;
 26.1231 +				}
 26.1232 +
 26.1233 +				/* If we're here, there was a spurious wake up
 26.1234 +				   or the read thread was shutdown. Run the
 26.1235 +				   loop again (ie: don't break). */
 26.1236 +			}
 26.1237 +			else if (res == ETIMEDOUT) {
 26.1238 +				/* Timed out. */
 26.1239 +				bytes_read = 0;
 26.1240 +				break;
 26.1241 +			}
 26.1242 +			else {
 26.1243 +				/* Error. */
 26.1244 +				bytes_read = -1;
 26.1245 +				break;
 26.1246 +			}
 26.1247 +		}
 26.1248 +	}
 26.1249 +	else {
 26.1250 +		/* Purely non-blocking */
 26.1251 +		bytes_read = 0;
 26.1252 +	}
 26.1253 +
 26.1254 +ret:
 26.1255 +	pthread_mutex_unlock(&dev->mutex);
 26.1256 +	pthread_cleanup_pop(0);
 26.1257 +
 26.1258 +	return bytes_read;
 26.1259 +}
 26.1260 +
 26.1261 +int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
 26.1262 +{
 26.1263 +	return hid_read_timeout(dev, data, length, dev->blocking ? -1 : 0);
 26.1264 +}
 26.1265 +
 26.1266 +int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
 26.1267 +{
 26.1268 +	dev->blocking = !nonblock;
 26.1269 +
 26.1270 +	return 0;
 26.1271 +}
 26.1272 +
 26.1273 +
 26.1274 +int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
 26.1275 +{
 26.1276 +	int res = -1;
 26.1277 +	int skipped_report_id = 0;
 26.1278 +	int report_number = data[0];
 26.1279 +
 26.1280 +	if (report_number == 0x0) {
 26.1281 +		data++;
 26.1282 +		length--;
 26.1283 +		skipped_report_id = 1;
 26.1284 +	}
 26.1285 +
 26.1286 +	res = libusb_control_transfer(dev->device_handle,
 26.1287 +		LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT,
 26.1288 +		0x09/*HID set_report*/,
 26.1289 +		(3/*HID feature*/ << 8) | report_number,
 26.1290 +		dev->interface,
 26.1291 +		(unsigned char *)data, length,
 26.1292 +		1000/*timeout millis*/);
 26.1293 +
 26.1294 +	if (res < 0)
 26.1295 +		return -1;
 26.1296 +
 26.1297 +	/* Account for the report ID */
 26.1298 +	if (skipped_report_id)
 26.1299 +		length++;
 26.1300 +
 26.1301 +	return length;
 26.1302 +}
 26.1303 +
 26.1304 +int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
 26.1305 +{
 26.1306 +	int res = -1;
 26.1307 +	int skipped_report_id = 0;
 26.1308 +	int report_number = data[0];
 26.1309 +
 26.1310 +	if (report_number == 0x0) {
 26.1311 +		/* Offset the return buffer by 1, so that the report ID
 26.1312 +		   will remain in byte 0. */
 26.1313 +		data++;
 26.1314 +		length--;
 26.1315 +		skipped_report_id = 1;
 26.1316 +	}
 26.1317 +	res = libusb_control_transfer(dev->device_handle,
 26.1318 +		LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN,
 26.1319 +		0x01/*HID get_report*/,
 26.1320 +		(3/*HID feature*/ << 8) | report_number,
 26.1321 +		dev->interface,
 26.1322 +		(unsigned char *)data, length,
 26.1323 +		1000/*timeout millis*/);
 26.1324 +
 26.1325 +	if (res < 0)
 26.1326 +		return -1;
 26.1327 +
 26.1328 +	if (skipped_report_id)
 26.1329 +		res++;
 26.1330 +
 26.1331 +	return res;
 26.1332 +}
 26.1333 +
 26.1334 +
 26.1335 +void HID_API_EXPORT hid_close(hid_device *dev)
 26.1336 +{
 26.1337 +	if (!dev)
 26.1338 +		return;
 26.1339 +
 26.1340 +	/* Cause read_thread() to stop. */
 26.1341 +	dev->shutdown_thread = 1;
 26.1342 +	libusb_cancel_transfer(dev->transfer);
 26.1343 +
 26.1344 +	/* Wait for read_thread() to end. */
 26.1345 +	pthread_join(dev->thread, NULL);
 26.1346 +
 26.1347 +	/* Clean up the Transfer objects allocated in read_thread(). */
 26.1348 +	free(dev->transfer->buffer);
 26.1349 +	libusb_free_transfer(dev->transfer);
 26.1350 +
 26.1351 +	/* release the interface */
 26.1352 +	libusb_release_interface(dev->device_handle, dev->interface);
 26.1353 +
 26.1354 +	/* Close the handle */
 26.1355 +	libusb_close(dev->device_handle);
 26.1356 +
 26.1357 +	/* Clear out the queue of received reports. */
 26.1358 +	pthread_mutex_lock(&dev->mutex);
 26.1359 +	while (dev->input_reports) {
 26.1360 +		return_data(dev, NULL, 0);
 26.1361 +	}
 26.1362 +	pthread_mutex_unlock(&dev->mutex);
 26.1363 +
 26.1364 +	free_hid_device(dev);
 26.1365 +}
 26.1366 +
 26.1367 +
 26.1368 +int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
 26.1369 +{
 26.1370 +	return hid_get_indexed_string(dev, dev->manufacturer_index, string, maxlen);
 26.1371 +}
 26.1372 +
 26.1373 +int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
 26.1374 +{
 26.1375 +	return hid_get_indexed_string(dev, dev->product_index, string, maxlen);
 26.1376 +}
 26.1377 +
 26.1378 +int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
 26.1379 +{
 26.1380 +	return hid_get_indexed_string(dev, dev->serial_index, string, maxlen);
 26.1381 +}
 26.1382 +
 26.1383 +int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
 26.1384 +{
 26.1385 +	wchar_t *str;
 26.1386 +
 26.1387 +	str = get_usb_string(dev->device_handle, string_index);
 26.1388 +	if (str) {
 26.1389 +		wcsncpy(string, str, maxlen);
 26.1390 +		string[maxlen-1] = L'\0';
 26.1391 +		free(str);
 26.1392 +		return 0;
 26.1393 +	}
 26.1394 +	else
 26.1395 +		return -1;
 26.1396 +}
 26.1397 +
 26.1398 +
 26.1399 +HID_API_EXPORT const wchar_t * HID_API_CALL  hid_error(hid_device *dev)
 26.1400 +{
 26.1401 +	return NULL;
 26.1402 +}
 26.1403 +
 26.1404 +
 26.1405 +struct lang_map_entry {
 26.1406 +	const char *name;
 26.1407 +	const char *string_code;
 26.1408 +	uint16_t usb_code;
 26.1409 +};
 26.1410 +
 26.1411 +#define LANG(name,code,usb_code) { name, code, usb_code }
 26.1412 +static struct lang_map_entry lang_map[] = {
 26.1413 +	LANG("Afrikaans", "af", 0x0436),
 26.1414 +	LANG("Albanian", "sq", 0x041C),
 26.1415 +	LANG("Arabic - United Arab Emirates", "ar_ae", 0x3801),
 26.1416 +	LANG("Arabic - Bahrain", "ar_bh", 0x3C01),
 26.1417 +	LANG("Arabic - Algeria", "ar_dz", 0x1401),
 26.1418 +	LANG("Arabic - Egypt", "ar_eg", 0x0C01),
 26.1419 +	LANG("Arabic - Iraq", "ar_iq", 0x0801),
 26.1420 +	LANG("Arabic - Jordan", "ar_jo", 0x2C01),
 26.1421 +	LANG("Arabic - Kuwait", "ar_kw", 0x3401),
 26.1422 +	LANG("Arabic - Lebanon", "ar_lb", 0x3001),
 26.1423 +	LANG("Arabic - Libya", "ar_ly", 0x1001),
 26.1424 +	LANG("Arabic - Morocco", "ar_ma", 0x1801),
 26.1425 +	LANG("Arabic - Oman", "ar_om", 0x2001),
 26.1426 +	LANG("Arabic - Qatar", "ar_qa", 0x4001),
 26.1427 +	LANG("Arabic - Saudi Arabia", "ar_sa", 0x0401),
 26.1428 +	LANG("Arabic - Syria", "ar_sy", 0x2801),
 26.1429 +	LANG("Arabic - Tunisia", "ar_tn", 0x1C01),
 26.1430 +	LANG("Arabic - Yemen", "ar_ye", 0x2401),
 26.1431 +	LANG("Armenian", "hy", 0x042B),
 26.1432 +	LANG("Azeri - Latin", "az_az", 0x042C),
 26.1433 +	LANG("Azeri - Cyrillic", "az_az", 0x082C),
 26.1434 +	LANG("Basque", "eu", 0x042D),
 26.1435 +	LANG("Belarusian", "be", 0x0423),
 26.1436 +	LANG("Bulgarian", "bg", 0x0402),
 26.1437 +	LANG("Catalan", "ca", 0x0403),
 26.1438 +	LANG("Chinese - China", "zh_cn", 0x0804),
 26.1439 +	LANG("Chinese - Hong Kong SAR", "zh_hk", 0x0C04),
 26.1440 +	LANG("Chinese - Macau SAR", "zh_mo", 0x1404),
 26.1441 +	LANG("Chinese - Singapore", "zh_sg", 0x1004),
 26.1442 +	LANG("Chinese - Taiwan", "zh_tw", 0x0404),
 26.1443 +	LANG("Croatian", "hr", 0x041A),
 26.1444 +	LANG("Czech", "cs", 0x0405),
 26.1445 +	LANG("Danish", "da", 0x0406),
 26.1446 +	LANG("Dutch - Netherlands", "nl_nl", 0x0413),
 26.1447 +	LANG("Dutch - Belgium", "nl_be", 0x0813),
 26.1448 +	LANG("English - Australia", "en_au", 0x0C09),
 26.1449 +	LANG("English - Belize", "en_bz", 0x2809),
 26.1450 +	LANG("English - Canada", "en_ca", 0x1009),
 26.1451 +	LANG("English - Caribbean", "en_cb", 0x2409),
 26.1452 +	LANG("English - Ireland", "en_ie", 0x1809),
 26.1453 +	LANG("English - Jamaica", "en_jm", 0x2009),
 26.1454 +	LANG("English - New Zealand", "en_nz", 0x1409),
 26.1455 +	LANG("English - Phillippines", "en_ph", 0x3409),
 26.1456 +	LANG("English - Southern Africa", "en_za", 0x1C09),
 26.1457 +	LANG("English - Trinidad", "en_tt", 0x2C09),
 26.1458 +	LANG("English - Great Britain", "en_gb", 0x0809),
 26.1459 +	LANG("English - United States", "en_us", 0x0409),
 26.1460 +	LANG("Estonian", "et", 0x0425),
 26.1461 +	LANG("Farsi", "fa", 0x0429),
 26.1462 +	LANG("Finnish", "fi", 0x040B),
 26.1463 +	LANG("Faroese", "fo", 0x0438),
 26.1464 +	LANG("French - France", "fr_fr", 0x040C),
 26.1465 +	LANG("French - Belgium", "fr_be", 0x080C),
 26.1466 +	LANG("French - Canada", "fr_ca", 0x0C0C),
 26.1467 +	LANG("French - Luxembourg", "fr_lu", 0x140C),
 26.1468 +	LANG("French - Switzerland", "fr_ch", 0x100C),
 26.1469 +	LANG("Gaelic - Ireland", "gd_ie", 0x083C),
 26.1470 +	LANG("Gaelic - Scotland", "gd", 0x043C),
 26.1471 +	LANG("German - Germany", "de_de", 0x0407),
 26.1472 +	LANG("German - Austria", "de_at", 0x0C07),
 26.1473 +	LANG("German - Liechtenstein", "de_li", 0x1407),
 26.1474 +	LANG("German - Luxembourg", "de_lu", 0x1007),
 26.1475 +	LANG("German - Switzerland", "de_ch", 0x0807),
 26.1476 +	LANG("Greek", "el", 0x0408),
 26.1477 +	LANG("Hebrew", "he", 0x040D),
 26.1478 +	LANG("Hindi", "hi", 0x0439),
 26.1479 +	LANG("Hungarian", "hu", 0x040E),
 26.1480 +	LANG("Icelandic", "is", 0x040F),
 26.1481 +	LANG("Indonesian", "id", 0x0421),
 26.1482 +	LANG("Italian - Italy", "it_it", 0x0410),
 26.1483 +	LANG("Italian - Switzerland", "it_ch", 0x0810),
 26.1484 +	LANG("Japanese", "ja", 0x0411),
 26.1485 +	LANG("Korean", "ko", 0x0412),
 26.1486 +	LANG("Latvian", "lv", 0x0426),
 26.1487 +	LANG("Lithuanian", "lt", 0x0427),
 26.1488 +	LANG("F.Y.R.O. Macedonia", "mk", 0x042F),
 26.1489 +	LANG("Malay - Malaysia", "ms_my", 0x043E),
 26.1490 +	LANG("Malay – Brunei", "ms_bn", 0x083E),
 26.1491 +	LANG("Maltese", "mt", 0x043A),
 26.1492 +	LANG("Marathi", "mr", 0x044E),
 26.1493 +	LANG("Norwegian - Bokml", "no_no", 0x0414),
 26.1494 +	LANG("Norwegian - Nynorsk", "no_no", 0x0814),
 26.1495 +	LANG("Polish", "pl", 0x0415),
 26.1496 +	LANG("Portuguese - Portugal", "pt_pt", 0x0816),
 26.1497 +	LANG("Portuguese - Brazil", "pt_br", 0x0416),
 26.1498 +	LANG("Raeto-Romance", "rm", 0x0417),
 26.1499 +	LANG("Romanian - Romania", "ro", 0x0418),
 26.1500 +	LANG("Romanian - Republic of Moldova", "ro_mo", 0x0818),
 26.1501 +	LANG("Russian", "ru", 0x0419),
 26.1502 +	LANG("Russian - Republic of Moldova", "ru_mo", 0x0819),
 26.1503 +	LANG("Sanskrit", "sa", 0x044F),
 26.1504 +	LANG("Serbian - Cyrillic", "sr_sp", 0x0C1A),
 26.1505 +	LANG("Serbian - Latin", "sr_sp", 0x081A),
 26.1506 +	LANG("Setsuana", "tn", 0x0432),
 26.1507 +	LANG("Slovenian", "sl", 0x0424),
 26.1508 +	LANG("Slovak", "sk", 0x041B),
 26.1509 +	LANG("Sorbian", "sb", 0x042E),
 26.1510 +	LANG("Spanish - Spain (Traditional)", "es_es", 0x040A),
 26.1511 +	LANG("Spanish - Argentina", "es_ar", 0x2C0A),
 26.1512 +	LANG("Spanish - Bolivia", "es_bo", 0x400A),
 26.1513 +	LANG("Spanish - Chile", "es_cl", 0x340A),
 26.1514 +	LANG("Spanish - Colombia", "es_co", 0x240A),
 26.1515 +	LANG("Spanish - Costa Rica", "es_cr", 0x140A),
 26.1516 +	LANG("Spanish - Dominican Republic", "es_do", 0x1C0A),
 26.1517 +	LANG("Spanish - Ecuador", "es_ec", 0x300A),
 26.1518 +	LANG("Spanish - Guatemala", "es_gt", 0x100A),
 26.1519 +	LANG("Spanish - Honduras", "es_hn", 0x480A),
 26.1520 +	LANG("Spanish - Mexico", "es_mx", 0x080A),
 26.1521 +	LANG("Spanish - Nicaragua", "es_ni", 0x4C0A),
 26.1522 +	LANG("Spanish - Panama", "es_pa", 0x180A),
 26.1523 +	LANG("Spanish - Peru", "es_pe", 0x280A),
 26.1524 +	LANG("Spanish - Puerto Rico", "es_pr", 0x500A),
 26.1525 +	LANG("Spanish - Paraguay", "es_py", 0x3C0A),
 26.1526 +	LANG("Spanish - El Salvador", "es_sv", 0x440A),
 26.1527 +	LANG("Spanish - Uruguay", "es_uy", 0x380A),
 26.1528 +	LANG("Spanish - Venezuela", "es_ve", 0x200A),
 26.1529 +	LANG("Southern Sotho", "st", 0x0430),
 26.1530 +	LANG("Swahili", "sw", 0x0441),
 26.1531 +	LANG("Swedish - Sweden", "sv_se", 0x041D),
 26.1532 +	LANG("Swedish - Finland", "sv_fi", 0x081D),
 26.1533 +	LANG("Tamil", "ta", 0x0449),
 26.1534 +	LANG("Tatar", "tt", 0X0444),
 26.1535 +	LANG("Thai", "th", 0x041E),
 26.1536 +	LANG("Turkish", "tr", 0x041F),
 26.1537 +	LANG("Tsonga", "ts", 0x0431),
 26.1538 +	LANG("Ukrainian", "uk", 0x0422),
 26.1539 +	LANG("Urdu", "ur", 0x0420),
 26.1540 +	LANG("Uzbek - Cyrillic", "uz_uz", 0x0843),
 26.1541 +	LANG("Uzbek – Latin", "uz_uz", 0x0443),
 26.1542 +	LANG("Vietnamese", "vi", 0x042A),
 26.1543 +	LANG("Xhosa", "xh", 0x0434),
 26.1544 +	LANG("Yiddish", "yi", 0x043D),
 26.1545 +	LANG("Zulu", "zu", 0x0435),
 26.1546 +	LANG(NULL, NULL, 0x0),
 26.1547 +};
 26.1548 +
 26.1549 +uint16_t get_usb_code_for_current_locale(void)
 26.1550 +{
 26.1551 +	char *locale;
 26.1552 +	char search_string[64];
 26.1553 +	char *ptr;
 26.1554 +	struct lang_map_entry *lang;
 26.1555 +
 26.1556 +	/* Get the current locale. */
 26.1557 +	locale = setlocale(0, NULL);
 26.1558 +	if (!locale)
 26.1559 +		return 0x0;
 26.1560 +
 26.1561 +	/* Make a copy of the current locale string. */
 26.1562 +	strncpy(search_string, locale, sizeof(search_string));
 26.1563 +	search_string[sizeof(search_string)-1] = '\0';
 26.1564 +
 26.1565 +	/* Chop off the encoding part, and make it lower case. */
 26.1566 +	ptr = search_string;
 26.1567 +	while (*ptr) {
 26.1568 +		*ptr = tolower(*ptr);
 26.1569 +		if (*ptr == '.') {
 26.1570 +			*ptr = '\0';
 26.1571 +			break;
 26.1572 +		}
 26.1573 +		ptr++;
 26.1574 +	}
 26.1575 +
 26.1576 +	/* Find the entry which matches the string code of our locale. */
 26.1577 +	lang = lang_map;
 26.1578 +	while (lang->string_code) {
 26.1579 +		if (!strcmp(lang->string_code, search_string)) {
 26.1580 +			return lang->usb_code;
 26.1581 +		}
 26.1582 +		lang++;
 26.1583 +	}
 26.1584 +
 26.1585 +	/* There was no match. Find with just the language only. */
 26.1586 +	/* Chop off the variant. Chop it off at the '_'. */
 26.1587 +	ptr = search_string;
 26.1588 +	while (*ptr) {
 26.1589 +		*ptr = tolower(*ptr);
 26.1590 +		if (*ptr == '_') {
 26.1591 +			*ptr = '\0';
 26.1592 +			break;
 26.1593 +		}
 26.1594 +		ptr++;
 26.1595 +	}
 26.1596 +
 26.1597 +#if 0 /* TODO: Do we need this? */
 26.1598 +	/* Find the entry which matches the string code of our language. */
 26.1599 +	lang = lang_map;
 26.1600 +	while (lang->string_code) {
 26.1601 +		if (!strcmp(lang->string_code, search_string)) {
 26.1602 +			return lang->usb_code;
 26.1603 +		}
 26.1604 +		lang++;
 26.1605 +	}
 26.1606 +#endif
 26.1607 +
 26.1608 +	/* Found nothing. */
 26.1609 +	return 0x0;
 26.1610 +}
 26.1611 +
 26.1612 +#if defined(__cplusplus) && !defined(NAMESPACE)
 26.1613 +}
 26.1614 +#endif
 26.1615 +
 26.1616 +#ifdef NAMESPACE
 26.1617 +}
 26.1618 +#endif
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/src/hidapi/libusb/hidusb.cpp	Thu Aug 09 16:05:48 2018 -0700
    27.3 @@ -0,0 +1,3 @@
    27.4 +
    27.5 +#define NAMESPACE HIDUSB
    27.6 +#include "hid.c"
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/src/hidapi/linux/Makefile-manual	Thu Aug 09 16:05:48 2018 -0700
    28.3 @@ -0,0 +1,49 @@
    28.4 +###########################################
    28.5 +# Simple Makefile for HIDAPI test program
    28.6 +#
    28.7 +# Alan Ott
    28.8 +# Signal 11 Software
    28.9 +# 2010-06-01
   28.10 +###########################################
   28.11 +
   28.12 +all: hidtest-hidraw libs
   28.13 +
   28.14 +libs: libhidapi-hidraw.so
   28.15 +
   28.16 +CC       ?= gcc
   28.17 +CFLAGS   ?= -Wall -g -fpic
   28.18 +
   28.19 +CXX      ?= g++
   28.20 +CXXFLAGS ?= -Wall -g -fpic
   28.21 +
   28.22 +LDFLAGS  ?= -Wall -g
   28.23 +
   28.24 +
   28.25 +COBJS     = hid.o
   28.26 +CPPOBJS   = ../hidtest/hidtest.o
   28.27 +OBJS      = $(COBJS) $(CPPOBJS)
   28.28 +LIBS_UDEV = `pkg-config libudev --libs` -lrt
   28.29 +LIBS      = $(LIBS_UDEV)
   28.30 +INCLUDES ?= -I../hidapi `pkg-config libusb-1.0 --cflags`
   28.31 +
   28.32 +
   28.33 +# Console Test Program
   28.34 +hidtest-hidraw: $(COBJS) $(CPPOBJS)
   28.35 +	$(CXX) $(LDFLAGS) $^ $(LIBS_UDEV) -o $@
   28.36 +
   28.37 +# Shared Libs
   28.38 +libhidapi-hidraw.so: $(COBJS)
   28.39 +	$(CC) $(LDFLAGS) $(LIBS_UDEV) -shared -fpic -Wl,-soname,$@.0 $^ -o $@
   28.40 +
   28.41 +# Objects
   28.42 +$(COBJS): %.o: %.c
   28.43 +	$(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@
   28.44 +
   28.45 +$(CPPOBJS): %.o: %.cpp
   28.46 +	$(CXX) $(CXXFLAGS) -c $(INCLUDES) $< -o $@
   28.47 +
   28.48 +
   28.49 +clean:
   28.50 +	rm -f $(OBJS) hidtest-hidraw libhidapi-hidraw.so ../hidtest/hidtest.o
   28.51 +
   28.52 +.PHONY: clean libs
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/src/hidapi/linux/Makefile.am	Thu Aug 09 16:05:48 2018 -0700
    29.3 @@ -0,0 +1,10 @@
    29.4 +lib_LTLIBRARIES = libhidapi-hidraw.la
    29.5 +libhidapi_hidraw_la_SOURCES = hid.c
    29.6 +libhidapi_hidraw_la_LDFLAGS = $(LTLDFLAGS)
    29.7 +AM_CPPFLAGS = -I$(top_srcdir)/hidapi/ $(CFLAGS_HIDRAW)
    29.8 +libhidapi_hidraw_la_LIBADD = $(LIBS_HIDRAW)
    29.9 +
   29.10 +hdrdir = $(includedir)/hidapi
   29.11 +hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h
   29.12 +
   29.13 +EXTRA_DIST = Makefile-manual
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/src/hidapi/linux/README.txt	Thu Aug 09 16:05:48 2018 -0700
    30.3 @@ -0,0 +1,59 @@
    30.4 +
    30.5 +There are two implementations of HIDAPI for Linux. One (linux/hid.c) uses the
    30.6 +Linux hidraw driver, and the other (libusb/hid.c) uses libusb. Which one you
    30.7 +use depends on your application. Complete functionality of the hidraw
    30.8 +version depends on patches to the Linux kernel which are not currently in
    30.9 +the mainline. These patches have to do with sending and receiving feature
   30.10 +reports. The libusb implementation uses libusb to talk directly to the
   30.11 +device, bypassing any Linux HID driver. The disadvantage of the libusb
   30.12 +version is that it will only work with USB devices, while the hidraw
   30.13 +implementation will work with Bluetooth devices as well.
   30.14 +
   30.15 +To use HIDAPI, simply drop either linux/hid.c or libusb/hid.c into your
   30.16 +application and build using the build parameters in the Makefile.
   30.17 +
   30.18 +
   30.19 +Libusb Implementation notes
   30.20 +----------------------------
   30.21 +For the libusb implementation, libusb-1.0 must be installed. Libusb 1.0 is
   30.22 +different than the legacy libusb 0.1 which is installed on many systems. To
   30.23 +install libusb-1.0 on Ubuntu and other Debian-based systems, run:
   30.24 +	sudo apt-get install libusb-1.0-0-dev
   30.25 +
   30.26 +
   30.27 +Hidraw Implementation notes
   30.28 +----------------------------
   30.29 +For the hidraw implementation, libudev headers and libraries are required to
   30.30 +build hidapi programs.  To install libudev libraries on Ubuntu,
   30.31 +and other Debian-based systems, run:
   30.32 +	sudo apt-get install libudev-dev
   30.33 +
   30.34 +On Redhat-based systems, run the following as root:
   30.35 +	yum install libudev-devel
   30.36 +
   30.37 +Unfortunately, the hidraw driver, which the linux version of hidapi is based
   30.38 +on, contains bugs in kernel versions < 2.6.36, which the client application
   30.39 +should be aware of.
   30.40 +
   30.41 +Bugs (hidraw implementation only):
   30.42 +-----------------------------------
   30.43 +On Kernel versions < 2.6.34, if your device uses numbered reports, an extra
   30.44 +byte will be returned at the beginning of all reports returned from read()
   30.45 +for hidraw devices. This is worked around in the libary. No action should be
   30.46 +necessary in the client library.
   30.47 +
   30.48 +On Kernel versions < 2.6.35, reports will only be sent using a Set_Report
   30.49 +transfer on the CONTROL endpoint. No data will ever be sent on an Interrupt
   30.50 +Out endpoint if one exists. This is fixed in 2.6.35. In 2.6.35, OUTPUT
   30.51 +reports will be sent to the device on the first INTERRUPT OUT endpoint if it
   30.52 +exists; If it does not exist, OUTPUT reports will be sent on the CONTROL
   30.53 +endpoint.
   30.54 +
   30.55 +On Kernel versions < 2.6.36, add an extra byte containing the report number
   30.56 +to sent reports if numbered reports are used, and the device does not
   30.57 +contain an INTERRPUT OUT endpoint for OUTPUT transfers.  For example, if
   30.58 +your device uses numbered reports and wants to send {0x2 0xff 0xff 0xff} to
   30.59 +the device (0x2 is the report number), you must send {0x2 0x2 0xff 0xff
   30.60 +0xff}. If your device has the optional Interrupt OUT endpoint, this does not
   30.61 +apply (but really on 2.6.35 only, because 2.6.34 won't use the interrupt
   30.62 +out endpoint).
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/src/hidapi/linux/hid.c	Thu Aug 09 16:05:48 2018 -0700
    31.3 @@ -0,0 +1,893 @@
    31.4 +/*******************************************************
    31.5 + HIDAPI - Multi-Platform l