Upstream official 0.12
This commit is contained in:
208
CHANGELOG
Normal file
208
CHANGELOG
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
---------------------------
|
||||||
|
-
|
||||||
|
- CHANGE LOG - Wiiuse
|
||||||
|
-
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
http://wiiuse.net/
|
||||||
|
http://wiiuse.sourceforge.net/
|
||||||
|
http://sourceforge.net/projects/wiiuse/
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
v0.12 -- 2 Apr 2008
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
Added:
|
||||||
|
- API function wiiuse_set_ir_sensitivity()
|
||||||
|
- Macro WIIUSE_GET_IR_SENSITIVITY()
|
||||||
|
- Event type WIIUSE_READ_DATA
|
||||||
|
- Event type WIIUSE_UNEXPECTED_DISCONNECT
|
||||||
|
|
||||||
|
Fixed:
|
||||||
|
- [Linux] Ability to try to select() nothing
|
||||||
|
- [Linux] Changed Makefile to include debug output when compiling in debug mode
|
||||||
|
|
||||||
|
Changed:
|
||||||
|
- wiiuse_set_nunchuk_orient_threshold() now takes a wiimote_t pointer
|
||||||
|
- wiiuse_set_nunchuk_accel_threshold() now takes a wiimote_t pointer
|
||||||
|
- wiiuse_read_data() generates an event WIIUSE_READ_DATA rather than executing a callback
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
v0.11 -- 25 Feb 2008
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
Added:
|
||||||
|
- API function wiiuse_set_nunchuk_orient_threshold()
|
||||||
|
- API function wiiuse_set_nunchuk_accel_threshold()
|
||||||
|
- Event type WIIUSE_NUNCHUK_INSERTED
|
||||||
|
- Event type WIIUSE_NUNCHUK_REMOVED
|
||||||
|
- Event type WIIUSE_CLASSIC_CTRL_INSERTED
|
||||||
|
- Event type WIIUSE_CLASSIC_CTRL_REMOVED
|
||||||
|
- Event type WIIUSE_GUITAR_HERO_3_CTRL_INSERTED
|
||||||
|
- Event type WIIUSE_GUITAR_HERO_3_CTRL_REMOVED
|
||||||
|
|
||||||
|
Fixed:
|
||||||
|
- Added some missing function prototypes to wiiuse.h
|
||||||
|
- [Linux] Fixed Makefile to link libmath and libbluetooth
|
||||||
|
- Status event is set when a status report comes in
|
||||||
|
- Orientation threshold not being saved in lstate
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
v0.10 -- 11 Feb 2008
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
Added:
|
||||||
|
- Real dynamic linking (by noisehole)
|
||||||
|
- Changed from callback to SDL style
|
||||||
|
- Guitar Hero 3 controller support
|
||||||
|
- API function wiiuse_set_accel_threshold()
|
||||||
|
- API function wiiuse_version()
|
||||||
|
- Macro WIIUSE_USING_SPEAKER()
|
||||||
|
- Macro WIIUSE_IS_LED_SET(wm, num)
|
||||||
|
- wiiuse_init() now autogenerates unids
|
||||||
|
- orient_t::a_roll/a_pitch
|
||||||
|
- wiiuse_resync()
|
||||||
|
- wiiuse_cleanup()
|
||||||
|
- wiiuse_set_timeout()
|
||||||
|
|
||||||
|
Fixed:
|
||||||
|
- [Windows] Fixed bug where it did not detect expansions on startup
|
||||||
|
- Renamed INFO/WARNING/DEBUG macros to WIIUSE_* (by noisehole)
|
||||||
|
- Updated Makefiles (by noisehole)
|
||||||
|
- Fixed incorrect roll/pitch when smoothing was enabled
|
||||||
|
- Fixed nunchuk and classic controller flooding events when significant changes occured
|
||||||
|
- Fixed bug where IR was not correct on roll if IR was enabled before handshake
|
||||||
|
|
||||||
|
Removed:
|
||||||
|
- wiiuse_startup(), no longer needed
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
v0.9 -- 3 Nov 2007
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
Fixed:
|
||||||
|
- Can now use include/wiiuse.h in C++ projects.
|
||||||
|
- HOME button works again.
|
||||||
|
- IR now functions after expansion is connected or removed.
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
v0.8 -- 27 Oct 2007
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
- Bumped API version to 8
|
||||||
|
- Exported all API functions for usage with non-C/C++ languages.
|
||||||
|
- Changed event callback to only trigger if a significant state change occurs.
|
||||||
|
|
||||||
|
Added:
|
||||||
|
- wiimote_t::lstate structure
|
||||||
|
|
||||||
|
Fixed:
|
||||||
|
- Bug 1820140 - Buffer overflow in io_nix.c. Thanks proppy.
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
v0.7 -- 19 Oct 2007
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
- Bumped API version to 7
|
||||||
|
- Renamed Linux build from wii.so to wiiuse.so
|
||||||
|
- Changed version representation from float to const char*.
|
||||||
|
|
||||||
|
Added:
|
||||||
|
- [Windows] BlueSoleil support.
|
||||||
|
- [Windows] Bluetooth stack auto-detection (WinXP SP2, Bluesoleil, Widdcomm tested).
|
||||||
|
- [Windows] API function wiiuse_set_bluetooth_stack().
|
||||||
|
- Calculates yaw if IR tracking is enabled.
|
||||||
|
|
||||||
|
Fixed:
|
||||||
|
- [Windows] Problem where a connection is made to a wiimote that does not exist.
|
||||||
|
- [Windows] Issue that occured while using multiple wiimotes.
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
v0.6 -- 16 Oct 2007
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
- Bumped API version to 0.6.
|
||||||
|
- Ported to Microsoft Windows.
|
||||||
|
- Improved IR tracking.
|
||||||
|
- Default IR virtual screen resolutions changed depending on 16:9 or 4:3.
|
||||||
|
|
||||||
|
Added:
|
||||||
|
- src/msvc/ and api/msvc/ - Microsoft Visual C++ 6.0 project files.
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
v0.5 -- 13 Oct 2007
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
- Bumped API version to 0.5.
|
||||||
|
- Greatly improved IR tracking.
|
||||||
|
- Renamed function wiiuse_set_ir_correction() to wiiuse_set_ir_position().
|
||||||
|
|
||||||
|
Added:
|
||||||
|
- API function wiiuse_set_aspect_ratio()
|
||||||
|
|
||||||
|
Fixed:
|
||||||
|
- When rolling around 180 degree rotation smoothing would not be seemless.
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
v0.4 -- 08 Oct 2007
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
- Bumped API version to 0.4.
|
||||||
|
- Greatly improved classic controller joystick functionality.
|
||||||
|
- Changed all functions named wiimote_*() to wiiuse_*()
|
||||||
|
- Renamed many macros from WIIMOTE_* to WIIUSE_*
|
||||||
|
|
||||||
|
Added:
|
||||||
|
- IR support
|
||||||
|
- New WIIMOTE_CONTINUOUS flag to set continuous reporting
|
||||||
|
- Macro IS_JUST_PRESSED()
|
||||||
|
- Macro WIIUSE_USING_ACC()
|
||||||
|
- Macro WIIUSE_USING_EXP()
|
||||||
|
- Macro WIIUSE_USING_IR()
|
||||||
|
- API function wiiuse_set_ir()
|
||||||
|
- API function wiiuse_set_ir_vres()
|
||||||
|
- API function wiiuse_set_ir_correction()
|
||||||
|
|
||||||
|
- gfx/ - A small OpenGL example that renders IR data
|
||||||
|
|
||||||
|
Fixed:
|
||||||
|
- Sometimes classic controller would only report infinite angle and magnitude for joysticks.
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
v0.3 -- 10 Sept 2007
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
- Moved license to GPLv3.
|
||||||
|
- Bumped API version to 0.3.
|
||||||
|
|
||||||
|
Added:
|
||||||
|
- Support for Classic Controller
|
||||||
|
- Smoothing for roll and pitch values of the wiimote and nunchuk.
|
||||||
|
|
||||||
|
- API: wiimote_set_flags() to set or disable wiimote options.
|
||||||
|
- API: wiimote_set_smooth_alpha() to set smoothing alpha value.
|
||||||
|
|
||||||
|
Fixed:
|
||||||
|
- When the wiimote accelerates the roll or pitch is unreliable and was set to 0.
|
||||||
|
It now remains at previous tilt value.
|
||||||
|
- If no event callback was specified then no events would be processed internally.
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
v0.2 -- 25 Aug 2007
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
- Bumped API version to 0.2.
|
||||||
|
|
||||||
|
Added:
|
||||||
|
- Nunchuk support.
|
||||||
|
- Ability to write to flash memory.
|
||||||
|
|
||||||
|
Fixed:
|
||||||
|
- Roll and pitch rotation now ranges from -180 to 180 degrees (previously -90 to 90).
|
||||||
|
- Bug when reading data from flash memory would read wrong address.
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
v0.1 -- 23 Feb 2007
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
- Initial release
|
||||||
620
LICENSE
Normal file
620
LICENSE
Normal file
@@ -0,0 +1,620 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
170
LICENSE_noncommercial
Normal file
170
LICENSE_noncommercial
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
This license can be used for any works that this license defines
|
||||||
|
as "derived" or "combined" works that are strictly NON-COMMERCIAL.
|
||||||
|
This license prohibits the use of any source or object code
|
||||||
|
in works that are PROPRIETARY.
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
||||||
23
Makefile
Normal file
23
Makefile
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#
|
||||||
|
# wiiuse Makefile
|
||||||
|
#
|
||||||
|
|
||||||
|
all clean install:
|
||||||
|
@$(MAKE) -C src $@
|
||||||
|
@$(MAKE) -C example $@
|
||||||
|
@$(MAKE) -C example-sdl $@
|
||||||
|
|
||||||
|
wiiuse:
|
||||||
|
@$(MAKE) -C src
|
||||||
|
|
||||||
|
ex:
|
||||||
|
@$(MAKE) -C example
|
||||||
|
|
||||||
|
sdl-ex:
|
||||||
|
@$(MAKE) -C example-sdl
|
||||||
|
|
||||||
|
distclean:
|
||||||
|
@$(MAKE) -C src $@
|
||||||
|
@$(MAKE) -C example $@
|
||||||
|
@$(MAKE) -C example-sdl $@
|
||||||
|
@find . -type f \( -name "*.save" -or -name "*~" -or -name gmon.out \) -delete &> /dev/null
|
||||||
155
README
Normal file
155
README
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
---------------------------
|
||||||
|
-
|
||||||
|
- README - Wiiuse
|
||||||
|
-
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
http://wiiuse.net/
|
||||||
|
http://wiiuse.sourceforge.net/
|
||||||
|
http://sourceforge.net/projects/wiiuse/
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
ABOUT
|
||||||
|
|
||||||
|
Wiiuse is a library written in C that connects with several Nintendo Wii remotes.
|
||||||
|
Supports motion sensing, IR tracking, nunchuk, classic controller, and the Guitar Hero 3 controller.
|
||||||
|
Single threaded and nonblocking makes a light weight and clean API.
|
||||||
|
|
||||||
|
Distributed under the GPL and LGPL.
|
||||||
|
|
||||||
|
|
||||||
|
AUTHORS
|
||||||
|
|
||||||
|
Michael Laforest < para >
|
||||||
|
Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
|
||||||
|
The following people have contributed patches to wiiuse:
|
||||||
|
- dhewg
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE
|
||||||
|
|
||||||
|
There are two licenses for wiiuse. Please read them carefully before choosing which one
|
||||||
|
you use. You may of course at any time switch the license you are currently using to
|
||||||
|
the other.
|
||||||
|
|
||||||
|
Briefly, the license options are:
|
||||||
|
|
||||||
|
a) GNU LGPL (modified for non-commercial usage only)
|
||||||
|
b) GNU GPL
|
||||||
|
|
||||||
|
PLEASE READ THE LICENSES!
|
||||||
|
|
||||||
|
|
||||||
|
ACKNOWLEDGEMENTS
|
||||||
|
|
||||||
|
http://wiibrew.org/
|
||||||
|
This site and their users have contributed an immense amount of information
|
||||||
|
about the wiimote and its technical details. I could not have written this program
|
||||||
|
without the vast amounts of reverse engineered information that was researched by them.
|
||||||
|
|
||||||
|
Nintendo
|
||||||
|
Of course Nintendo for designing and manufacturing the Wii and Wii remote.
|
||||||
|
|
||||||
|
BlueZ
|
||||||
|
Easy and intuitive bluetooth stack for Linux.
|
||||||
|
|
||||||
|
Thanks to Brent for letting me borrow his Guitar Hero 3 controller.
|
||||||
|
|
||||||
|
|
||||||
|
DISCLAIMER AND WARNINGS
|
||||||
|
|
||||||
|
I am in no way responsible for any damages or effects, intended or not, caused by this program.
|
||||||
|
|
||||||
|
*** WARNING *** WARNING *** WARNING ***
|
||||||
|
|
||||||
|
Be aware that writing to memory may damage or destroy your wiimote or expansions.
|
||||||
|
|
||||||
|
*** WARNING *** WARNING *** WARNING ***
|
||||||
|
|
||||||
|
This program was written using reverse engineered specifications available from wiibrew.org.
|
||||||
|
Therefore the operation of this program may not be entirely correct.
|
||||||
|
Results obtained by using this program may vary.
|
||||||
|
|
||||||
|
|
||||||
|
AUDIENCE
|
||||||
|
|
||||||
|
This project is intended for developers who wish to include support for the Nintendo Wii remote
|
||||||
|
with their third party application. Please be aware that by using this software you are bound
|
||||||
|
to the terms of the GNU GPL.
|
||||||
|
|
||||||
|
|
||||||
|
PLATFORMS AND DEPENDENCIES
|
||||||
|
|
||||||
|
Wiiuse currently operates on both Linux and Windows.
|
||||||
|
You will need:
|
||||||
|
|
||||||
|
For Linux:
|
||||||
|
- The kernel must support bluetooth
|
||||||
|
- The BlueZ bluetooth drivers must be installed
|
||||||
|
|
||||||
|
For Windows:
|
||||||
|
- Bluetooth driver (tested with Microsoft's stack with Windows XP SP2)
|
||||||
|
- If compiling, Microsoft Windows Driver Development Kit (DDK)
|
||||||
|
|
||||||
|
|
||||||
|
COMPILING
|
||||||
|
|
||||||
|
Linux:
|
||||||
|
You need SDL and OpenGL installed to compile the SDL example.
|
||||||
|
|
||||||
|
# make [target]
|
||||||
|
|
||||||
|
If 'target' is omitted then everything is compiled.
|
||||||
|
|
||||||
|
Where 'target' can be any of the following:
|
||||||
|
|
||||||
|
- wiiuse
|
||||||
|
Compiles libwiiuse.so
|
||||||
|
|
||||||
|
- ex
|
||||||
|
Compiles wiiuse-example
|
||||||
|
|
||||||
|
- sdl-ex
|
||||||
|
Compiles wiiuse-sdl
|
||||||
|
|
||||||
|
Become root.
|
||||||
|
|
||||||
|
# make install
|
||||||
|
|
||||||
|
The above command will only install the binaries that you
|
||||||
|
selected to compile.
|
||||||
|
|
||||||
|
wiiuse.so is installed to /usr/lib
|
||||||
|
wiiuse-example and wiiuse-sdl are installed to /usr/bin
|
||||||
|
|
||||||
|
Windows:
|
||||||
|
A Microsoft Visual C++ 6.0 project file has been included.
|
||||||
|
|
||||||
|
You need the install the Windows DDK (driver development kit)
|
||||||
|
to compile wiiuse. Make sure you include the inc/ and lib/
|
||||||
|
directories from the DDK in your IDE include and library paths.
|
||||||
|
You can download this from here:
|
||||||
|
http://www.microsoft.com/whdc/devtools/ddk/default.mspx
|
||||||
|
|
||||||
|
You need to link the following libraries (already set in the
|
||||||
|
included project file):
|
||||||
|
- Ws2_32.lib
|
||||||
|
- hid.lib
|
||||||
|
- setupapi.lib
|
||||||
|
|
||||||
|
|
||||||
|
USING THE LIBRARY IN A THIRD PARTY APPLICATION
|
||||||
|
|
||||||
|
To use the library in your own program you must first compile wiiuse as a module.
|
||||||
|
Include include/wiiuse.h in any file that uses wiiuse.
|
||||||
|
|
||||||
|
For Linux you must link wiiuse.so ( -lwiiuse ).
|
||||||
|
For Windows you must link wiiuse.lib. When your program runs it will need wiiuse.dll.
|
||||||
|
|
||||||
|
|
||||||
|
BUGS
|
||||||
|
|
||||||
|
On Windows using more than one wiimote (usually more than two wiimotes) may cause
|
||||||
|
significant latency.
|
||||||
83
example-sdl/Makefile
Normal file
83
example-sdl/Makefile
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
#
|
||||||
|
# wiiuse Makefile
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Change this to your GCC version.
|
||||||
|
#
|
||||||
|
CC = gcc
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
#
|
||||||
|
# You should not need to edit below this line.
|
||||||
|
#
|
||||||
|
####################################################
|
||||||
|
|
||||||
|
#
|
||||||
|
# Universal cflags
|
||||||
|
#
|
||||||
|
CFLAGS = -Wall -pipe -fPIC -funroll-loops
|
||||||
|
|
||||||
|
ifeq ($(debug),1)
|
||||||
|
OBJ_PREFIX = debug
|
||||||
|
CFLAGS += -g -pg -DWITH_WIIUSE_DEBUG
|
||||||
|
else
|
||||||
|
OBJ_PREFIX = release
|
||||||
|
CFLAGS += -O2
|
||||||
|
endif
|
||||||
|
|
||||||
|
OBJ_DIR = $(OBJ_PREFIX)-$(shell $(CC) -v 2>&1|grep ^Target:|cut -d' ' -f2)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Linking flags
|
||||||
|
#
|
||||||
|
LDFLAGS = -L../src/$(OBJ_DIR) -lm -lGL -lGLU -lglut -lSDL -lbluetooth -lwiiuse
|
||||||
|
|
||||||
|
#
|
||||||
|
# Target binaries (always created as BIN)
|
||||||
|
#
|
||||||
|
BIN = ./$(OBJ_DIR)/wiiuse-sdl
|
||||||
|
|
||||||
|
#
|
||||||
|
# Inclusion paths.
|
||||||
|
#
|
||||||
|
INCLUDES = -I../src/ -I/usr/include/SDL
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate a list of object files
|
||||||
|
#
|
||||||
|
OBJS = $(OBJ_DIR)/sdl.o
|
||||||
|
|
||||||
|
###############################
|
||||||
|
#
|
||||||
|
# Build targets.
|
||||||
|
#
|
||||||
|
###############################
|
||||||
|
|
||||||
|
all: $(BIN)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@-rm $(OBJS) 2> /dev/null
|
||||||
|
|
||||||
|
distclean: clean
|
||||||
|
@-rm -r debug-* release-* 2> /dev/null
|
||||||
|
|
||||||
|
install:
|
||||||
|
@if [ -e $(BIN) ]; then \
|
||||||
|
cp -v $(BIN) /usr/bin ;\
|
||||||
|
fi
|
||||||
|
|
||||||
|
$(BIN): mkdir $(OBJS)
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(BIN)
|
||||||
|
|
||||||
|
$(OBJ_DIR)/%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
|
||||||
|
|
||||||
|
mkdir:
|
||||||
|
@if [ ! -d $(OBJ_DIR) ]; then \
|
||||||
|
mkdir $(OBJ_DIR); \
|
||||||
|
fi
|
||||||
|
|
||||||
|
run: all
|
||||||
|
LD_LIBRARY_PATH=`pwd`/../src/$(OBJ_DIR):$(LD_LIBRARY_PATH) $(BIN)
|
||||||
|
|
||||||
111
example-sdl/msvc/wiiusesdl.dsp
Normal file
111
example-sdl/msvc/wiiusesdl.dsp
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
# Microsoft Developer Studio Project File - Name="wiiusesdl" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Application" 0x0101
|
||||||
|
|
||||||
|
CFG=wiiusesdl - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "wiiusesdl.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "wiiusesdl.mak" CFG="wiiusesdl - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "wiiusesdl - Win32 Release" (based on "Win32 (x86) Application")
|
||||||
|
!MESSAGE "wiiusesdl - Win32 Debug" (based on "Win32 (x86) Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
MTL=midl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "wiiusesdl - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /W3 /GX /O2 /I "..\..\src" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sdl.lib opengl32.lib glu32.lib wiiuse.lib /nologo /subsystem:windows /machine:I386
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "wiiusesdl - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\src" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sdl.lib opengl32.lib glu32.lib wiiuse.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "wiiusesdl - Win32 Release"
|
||||||
|
# Name "wiiusesdl - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\sdl.c
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\src\wiiuse.h
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Resource Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
||||||
29
example-sdl/msvc/wiiusesdl.dsw
Normal file
29
example-sdl/msvc/wiiusesdl.dsw
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||||
|
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "wiiusesdl"=".\wiiusesdl.dsp" - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Global:
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<3>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
BIN
example-sdl/msvc/wiiusesdl.ncb
Normal file
BIN
example-sdl/msvc/wiiusesdl.ncb
Normal file
Binary file not shown.
BIN
example-sdl/msvc/wiiusesdl.opt
Normal file
BIN
example-sdl/msvc/wiiusesdl.opt
Normal file
Binary file not shown.
439
example-sdl/sdl.c
Normal file
439
example-sdl/sdl.c
Normal file
@@ -0,0 +1,439 @@
|
|||||||
|
/*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
#else
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <GL/glu.h>
|
||||||
|
#include <GL/glut.h>
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
|
#include <wiiuse.h>
|
||||||
|
|
||||||
|
#define PI 3.14159265358979323846
|
||||||
|
#define PI_DIV_180 0.017453292519943296
|
||||||
|
#define deg PI_DIV_180
|
||||||
|
|
||||||
|
#define MAX_WIIMOTES 2
|
||||||
|
|
||||||
|
GLint width = 1024, height = 768;
|
||||||
|
GLfloat backColor[4] = {1.0,1.0,1.0,1.0};
|
||||||
|
|
||||||
|
wiimote** wiimotes = NULL;
|
||||||
|
|
||||||
|
int last_dots[4][2] = {{0}};
|
||||||
|
int xcoord = 0;
|
||||||
|
int ycoord = 0;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
DWORD last_render;
|
||||||
|
#else
|
||||||
|
struct timeval last_render;
|
||||||
|
int last_sec = 0;
|
||||||
|
int fps = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum render_mode_t {
|
||||||
|
IR = 1,
|
||||||
|
TEAPOT
|
||||||
|
};
|
||||||
|
enum render_mode_t render_mode = IR;
|
||||||
|
|
||||||
|
/* light information */
|
||||||
|
struct light_t {
|
||||||
|
GLfloat position[4];
|
||||||
|
GLfloat spotDirection[3];
|
||||||
|
GLfloat ambient[4];
|
||||||
|
GLfloat diffuse[4];
|
||||||
|
GLfloat specular[4];
|
||||||
|
GLfloat spotCutoff;
|
||||||
|
GLfloat spotExponent;
|
||||||
|
GLfloat spotAttenuation[3]; /* [0] = constant, [1] = linear, [2] = quadratic */
|
||||||
|
};
|
||||||
|
struct light_t light = {
|
||||||
|
{ 1.0, 1.0, -2.0, 1.0 },
|
||||||
|
{ -1.0, -1.0, 2.0 },
|
||||||
|
{ 0.0, 0.0, 0.0, 1.0 },
|
||||||
|
{ 1.0, 1.0, 1.0, 1.0 },
|
||||||
|
{ 1.0, 1.0, 1.0, 1.0 },
|
||||||
|
180.0, 0.0,
|
||||||
|
{ 1.0, 0.0, 0.0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* material information */
|
||||||
|
struct material_t {
|
||||||
|
GLfloat ambient[4];
|
||||||
|
GLfloat diffuse[4];
|
||||||
|
GLfloat specular[4];
|
||||||
|
GLfloat emission[4];
|
||||||
|
GLfloat shininess;
|
||||||
|
};
|
||||||
|
struct material_t red_plastic = {
|
||||||
|
{ 0.3, 0.0, 0.0, 1.0 },
|
||||||
|
{ 0.3, 0.0, 0.0, 1.0 },
|
||||||
|
{ 0.8, 0.6, 0.6, 1.0 },
|
||||||
|
{ 0.0, 0.0, 0.0, 1.0 },
|
||||||
|
32.0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void handle_event(struct wiimote_t* wm);
|
||||||
|
void display();
|
||||||
|
void update_light(GLenum l, struct light_t* lptr);
|
||||||
|
void set_material(struct material_t* mptr);
|
||||||
|
void resize_window(GLint new_width, GLint new_height);
|
||||||
|
|
||||||
|
void handle_event(struct wiimote_t* wm) {
|
||||||
|
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_PLUS))
|
||||||
|
wiiuse_motion_sensing(wm, 1);
|
||||||
|
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_MINUS))
|
||||||
|
wiiuse_motion_sensing(wm, 0);
|
||||||
|
|
||||||
|
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_UP))
|
||||||
|
wiiuse_set_ir(wm, 1);
|
||||||
|
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_DOWN))
|
||||||
|
wiiuse_set_ir(wm, 0);
|
||||||
|
|
||||||
|
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_B))
|
||||||
|
wiiuse_toggle_rumble(wm);
|
||||||
|
|
||||||
|
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_ONE)) {
|
||||||
|
int level;
|
||||||
|
WIIUSE_GET_IR_SENSITIVITY(wm, &level);
|
||||||
|
wiiuse_set_ir_sensitivity(wm, level+1);
|
||||||
|
}
|
||||||
|
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_TWO)) {
|
||||||
|
int level;
|
||||||
|
WIIUSE_GET_IR_SENSITIVITY(wm, &level);
|
||||||
|
wiiuse_set_ir_sensitivity(wm, level-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_A)) {
|
||||||
|
if (render_mode == IR)
|
||||||
|
render_mode = TEAPOT;
|
||||||
|
else
|
||||||
|
render_mode = IR;
|
||||||
|
resize_window(width, height);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DRAW_TRIANGLE(x, y, z, s) do { \
|
||||||
|
glVertex3f(x, y-s, z); \
|
||||||
|
glVertex3f(x+s, y+s, z); \
|
||||||
|
glVertex3f(x-s, y+s, z); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
int can_render() {
|
||||||
|
/* quick fps limit to ~60fps -- not too fancy, could be better */
|
||||||
|
#ifdef WIN32
|
||||||
|
if (GetTickCount() < (last_render + 16))
|
||||||
|
return 0;
|
||||||
|
last_render = GetTickCount();
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
struct timeval now;
|
||||||
|
long elapsed_usec = 0;
|
||||||
|
|
||||||
|
gettimeofday(&now, NULL);
|
||||||
|
|
||||||
|
if (now.tv_usec > 1000000) {
|
||||||
|
now.tv_usec -= 1000000;
|
||||||
|
++now.tv_sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (now.tv_sec > last_render.tv_sec)
|
||||||
|
elapsed_usec = ((now.tv_sec - last_render.tv_sec) * 1000000);
|
||||||
|
|
||||||
|
if (now.tv_usec > last_render.tv_usec)
|
||||||
|
elapsed_usec += now.tv_usec - last_render.tv_usec;
|
||||||
|
else
|
||||||
|
elapsed_usec += last_render.tv_usec - now.tv_usec;
|
||||||
|
|
||||||
|
if (time(NULL) > last_sec) {
|
||||||
|
printf("fps: %i\n", fps);
|
||||||
|
fps = 0;
|
||||||
|
last_sec = time(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elapsed_usec < 16000)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
last_render = now;
|
||||||
|
++fps;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void display() {
|
||||||
|
int i, wm;
|
||||||
|
float size = 5;
|
||||||
|
|
||||||
|
if (!can_render())
|
||||||
|
return;
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
if (render_mode == IR) {
|
||||||
|
/* draw the IR stuff */
|
||||||
|
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
|
/* green center */
|
||||||
|
glColor3f(0.0, 1.0, 0.0);
|
||||||
|
DRAW_TRIANGLE(width/2, height/2, 0, size);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
for (wm = 0; wm < MAX_WIIMOTES; ++wm) {
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
|
/* red ir */
|
||||||
|
glColor3f(1.0, 0.0, 0.0);
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
if (wiimotes[wm]->ir.dot[i].visible)
|
||||||
|
DRAW_TRIANGLE(wiimotes[wm]->ir.dot[i].rx, wiimotes[wm]->ir.dot[i].ry, 0, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* yellow corrected ir */
|
||||||
|
glColor3f(1.0, 1.0, 0.0);
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
if (wiimotes[wm]->ir.dot[i].visible)
|
||||||
|
DRAW_TRIANGLE(wiimotes[wm]->ir.dot[i].x, wiimotes[wm]->ir.dot[i].y, 0, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* blue cursor */
|
||||||
|
glColor3f(0.0, 0.0, 1.0);
|
||||||
|
DRAW_TRIANGLE(wiimotes[wm]->ir.x, wiimotes[wm]->ir.y-size, 0, size);
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* draw the teapot */
|
||||||
|
gluLookAt(0.0, 0.0, -5.0,
|
||||||
|
0.0, 0.0, 0.0,
|
||||||
|
0.0, 1.0, 0.0);
|
||||||
|
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
glEnable(GL_LIGHT0);
|
||||||
|
update_light(GL_LIGHT0, &light);
|
||||||
|
set_material(&red_plastic);
|
||||||
|
|
||||||
|
glRotatef(wiimotes[0]->orient.roll, 0.0f, 0.0f, 1.0f);
|
||||||
|
glRotatef(wiimotes[0]->orient.pitch, 1.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
|
||||||
|
glutSolidTeapot(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_GL_SwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void update_light(GLenum l, struct light_t* lptr) {
|
||||||
|
glLightfv(l, GL_POSITION, lptr->position);
|
||||||
|
glLightfv(l, GL_DIFFUSE, lptr->diffuse);
|
||||||
|
glLightfv(l, GL_SPECULAR, lptr->specular);
|
||||||
|
glLightfv(l, GL_AMBIENT, lptr->ambient);
|
||||||
|
glLightfv(l, GL_SPOT_DIRECTION, lptr->spotDirection);
|
||||||
|
glLightf(l, GL_SPOT_CUTOFF, lptr->spotCutoff);
|
||||||
|
glLightf(l, GL_SPOT_EXPONENT, lptr->spotExponent);
|
||||||
|
glLightf(l, GL_CONSTANT_ATTENUATION, lptr->spotAttenuation[0]);
|
||||||
|
glLightf(l, GL_LINEAR_ATTENUATION, lptr->spotAttenuation[1]);
|
||||||
|
glLightf(l, GL_QUADRATIC_ATTENUATION, lptr->spotAttenuation[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void set_material(struct material_t* mptr) {
|
||||||
|
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mptr->ambient);
|
||||||
|
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mptr->diffuse);
|
||||||
|
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mptr->specular);
|
||||||
|
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, mptr->shininess);
|
||||||
|
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mptr->emission);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void resize_window(GLint new_width, GLint new_height) {
|
||||||
|
int wm;
|
||||||
|
|
||||||
|
width = new_width;
|
||||||
|
height = new_height;
|
||||||
|
|
||||||
|
if (new_height == 0)
|
||||||
|
new_height = 1;
|
||||||
|
|
||||||
|
SDL_SetVideoMode(width, height, 16, SDL_RESIZABLE | SDL_OPENGL);
|
||||||
|
|
||||||
|
glViewport(0, 0, new_width, new_height);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
if (render_mode == IR)
|
||||||
|
gluOrtho2D(0, width, height, 0);
|
||||||
|
else
|
||||||
|
gluPerspective(60.0f, (float)new_width/(float)new_height, 0.1f, 100.0f);
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
width = new_width;
|
||||||
|
height = new_height;
|
||||||
|
|
||||||
|
for (wm = 0; wm < MAX_WIIMOTES; ++wm)
|
||||||
|
wiiuse_set_ir_vres(wiimotes[wm], width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
#else
|
||||||
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
|
||||||
|
#endif
|
||||||
|
int found, connected;
|
||||||
|
int wm;
|
||||||
|
|
||||||
|
//printf("wiiuse version = %s\n", wiiuse_version());
|
||||||
|
|
||||||
|
wiimotes = wiiuse_init(MAX_WIIMOTES);
|
||||||
|
found = wiiuse_find(wiimotes, MAX_WIIMOTES, 5);
|
||||||
|
if (!found)
|
||||||
|
return 0;
|
||||||
|
connected = wiiuse_connect(wiimotes, MAX_WIIMOTES);
|
||||||
|
if (connected)
|
||||||
|
printf("Connected to %i wiimotes (of %i found).\n", connected, found);
|
||||||
|
else {
|
||||||
|
printf("Failed to connect to any wiimote.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
wiiuse_set_leds(wiimotes[0], WIIMOTE_LED_1 | WIIMOTE_LED_4);
|
||||||
|
wiiuse_set_leds(wiimotes[1], WIIMOTE_LED_2 | WIIMOTE_LED_4);
|
||||||
|
wiiuse_rumble(wiimotes[0], 1);
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
usleep(200000);
|
||||||
|
#else
|
||||||
|
Sleep(200);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wiiuse_rumble(wiimotes[0], 0);
|
||||||
|
|
||||||
|
/* enable IR and motion sensing for all wiimotes */
|
||||||
|
for (wm = 0; wm < MAX_WIIMOTES; ++wm) {
|
||||||
|
wiiuse_motion_sensing(wiimotes[wm], 1);
|
||||||
|
wiiuse_set_ir(wiimotes[wm], 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||||
|
printf("Failed to initialize SDL: %s\n", SDL_GetError());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_WM_SetCaption("wiiuse SDL IR Example", "wiiuse SDL IR Example");
|
||||||
|
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
|
||||||
|
|
||||||
|
/* set window size */
|
||||||
|
width = wiimotes[0]->ir.vres[0];
|
||||||
|
height = wiimotes[0]->ir.vres[1];
|
||||||
|
SDL_SetVideoMode(width, height, 16, SDL_RESIZABLE | SDL_OPENGL);
|
||||||
|
|
||||||
|
for (wm = 0; wm < MAX_WIIMOTES; ++wm)
|
||||||
|
wiiuse_set_ir_vres(wiimotes[wm], width, height);
|
||||||
|
|
||||||
|
/* set OpenGL stuff */
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
glEnable(GL_NORMALIZE);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
glClearColor(0, 0, 0, 0);
|
||||||
|
|
||||||
|
/* set the size of the window */
|
||||||
|
resize_window(width, height);
|
||||||
|
|
||||||
|
display();
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
last_render = GetTickCount();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
SDL_Event event;
|
||||||
|
|
||||||
|
if (SDL_PollEvent(&event)) {
|
||||||
|
switch (event.type) {
|
||||||
|
case SDL_VIDEORESIZE:
|
||||||
|
{
|
||||||
|
/* resize the window */
|
||||||
|
resize_window(event.resize.w, event.resize.h);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDL_QUIT:
|
||||||
|
{
|
||||||
|
/* shutdown */
|
||||||
|
SDL_Quit();
|
||||||
|
wiiuse_cleanup(wiimotes, MAX_WIIMOTES);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wiiuse_poll(wiimotes, MAX_WIIMOTES)) {
|
||||||
|
/*
|
||||||
|
* This happens if something happened on any wiimote.
|
||||||
|
* So go through each one and check if anything happened.
|
||||||
|
*/
|
||||||
|
int i = 0;
|
||||||
|
for (; i < MAX_WIIMOTES; ++i) {
|
||||||
|
switch (wiimotes[i]->event) {
|
||||||
|
case WIIUSE_EVENT:
|
||||||
|
/* a generic event occured */
|
||||||
|
handle_event(wiimotes[i]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
display();
|
||||||
|
}
|
||||||
|
}
|
||||||
84
example/Makefile
Normal file
84
example/Makefile
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#
|
||||||
|
# wiiuse Makefile
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Change this to your GCC version.
|
||||||
|
#
|
||||||
|
CC = gcc
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
#
|
||||||
|
# You should not need to edit below this line.
|
||||||
|
#
|
||||||
|
####################################################
|
||||||
|
|
||||||
|
#
|
||||||
|
# Universal cflags
|
||||||
|
#
|
||||||
|
CFLAGS = -Wall -pipe -fPIC -funroll-loops
|
||||||
|
|
||||||
|
ifeq ($(debug),1)
|
||||||
|
OBJ_PREFIX = debug
|
||||||
|
CFLAGS += -g -pg -DWITH_WIIUSE_DEBUG
|
||||||
|
else
|
||||||
|
OBJ_PREFIX = release
|
||||||
|
CFLAGS += -O2
|
||||||
|
endif
|
||||||
|
|
||||||
|
OBJ_DIR = $(OBJ_PREFIX)-$(shell $(CC) -v 2>&1|grep ^Target:|cut -d' ' -f2)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Linking flags
|
||||||
|
#
|
||||||
|
LDFLAGS = -L../src/$(OBJ_DIR) -lm -lwiiuse
|
||||||
|
|
||||||
|
#
|
||||||
|
# Target binaries (always created as BIN)
|
||||||
|
#
|
||||||
|
BIN = ./$(OBJ_DIR)/wiiuse-example
|
||||||
|
|
||||||
|
#
|
||||||
|
# Inclusion paths.
|
||||||
|
#
|
||||||
|
INCLUDES = -I../src/
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate a list of object files
|
||||||
|
#
|
||||||
|
OBJS = $(OBJ_DIR)/example.o
|
||||||
|
|
||||||
|
###############################
|
||||||
|
#
|
||||||
|
# Build targets.
|
||||||
|
#
|
||||||
|
###############################
|
||||||
|
|
||||||
|
all: $(BIN)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@-rm $(OBJS) 2> /dev/null
|
||||||
|
|
||||||
|
distclean:
|
||||||
|
@-rm -r debug-* release-* 2> /dev/null
|
||||||
|
|
||||||
|
install:
|
||||||
|
@if [ -e $(BIN) ]; then \
|
||||||
|
cp -v $(BIN) /usr/bin ; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
$(BIN): mkdir $(OBJS)
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(BIN)
|
||||||
|
|
||||||
|
$(OBJ_DIR)/%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
|
||||||
|
|
||||||
|
mkdir:
|
||||||
|
@if [ ! -d $(OBJ_DIR) ]; then \
|
||||||
|
mkdir $(OBJ_DIR); \
|
||||||
|
fi
|
||||||
|
|
||||||
|
run: all
|
||||||
|
LD_LIBRARY_PATH=`pwd`/../src/$(OBJ_DIR):$(LD_LIBRARY_PATH) $(BIN)
|
||||||
|
|
||||||
437
example/example.c
Normal file
437
example/example.c
Normal file
@@ -0,0 +1,437 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @brief Example using the wiiuse API.
|
||||||
|
*
|
||||||
|
* This file is an example of how to use the wiiuse library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "wiiuse.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_WIIMOTES 4
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback that handles an event.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
*
|
||||||
|
* This function is called automatically by the wiiuse library when an
|
||||||
|
* event occurs on the specified wiimote.
|
||||||
|
*/
|
||||||
|
void handle_event(struct wiimote_t* wm) {
|
||||||
|
printf("\n\n--- EVENT [id %i] ---\n", wm->unid);
|
||||||
|
|
||||||
|
/* if a button is pressed, report it */
|
||||||
|
if (IS_PRESSED(wm, WIIMOTE_BUTTON_A)) printf("A pressed\n");
|
||||||
|
if (IS_PRESSED(wm, WIIMOTE_BUTTON_B)) printf("B pressed\n");
|
||||||
|
if (IS_PRESSED(wm, WIIMOTE_BUTTON_UP)) printf("UP pressed\n");
|
||||||
|
if (IS_PRESSED(wm, WIIMOTE_BUTTON_DOWN)) printf("DOWN pressed\n");
|
||||||
|
if (IS_PRESSED(wm, WIIMOTE_BUTTON_LEFT)) printf("LEFT pressed\n");
|
||||||
|
if (IS_PRESSED(wm, WIIMOTE_BUTTON_RIGHT)) printf("RIGHT pressed\n");
|
||||||
|
if (IS_PRESSED(wm, WIIMOTE_BUTTON_MINUS)) printf("MINUS pressed\n");
|
||||||
|
if (IS_PRESSED(wm, WIIMOTE_BUTTON_PLUS)) printf("PLUS pressed\n");
|
||||||
|
if (IS_PRESSED(wm, WIIMOTE_BUTTON_ONE)) printf("ONE pressed\n");
|
||||||
|
if (IS_PRESSED(wm, WIIMOTE_BUTTON_TWO)) printf("TWO pressed\n");
|
||||||
|
if (IS_PRESSED(wm, WIIMOTE_BUTTON_HOME)) printf("HOME pressed\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pressing minus will tell the wiimote we are no longer interested in movement.
|
||||||
|
* This is useful because it saves battery power.
|
||||||
|
*/
|
||||||
|
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_MINUS))
|
||||||
|
wiiuse_motion_sensing(wm, 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pressing plus will tell the wiimote we are interested in movement.
|
||||||
|
*/
|
||||||
|
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_PLUS))
|
||||||
|
wiiuse_motion_sensing(wm, 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pressing B will toggle the rumble
|
||||||
|
*
|
||||||
|
* if B is pressed but is not held, toggle the rumble
|
||||||
|
*/
|
||||||
|
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_B))
|
||||||
|
wiiuse_toggle_rumble(wm);
|
||||||
|
|
||||||
|
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_UP))
|
||||||
|
wiiuse_set_ir(wm, 1);
|
||||||
|
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_DOWN))
|
||||||
|
wiiuse_set_ir(wm, 0);
|
||||||
|
|
||||||
|
/* if the accelerometer is turned on then print angles */
|
||||||
|
if (WIIUSE_USING_ACC(wm)) {
|
||||||
|
printf("wiimote roll = %f [%f]\n", wm->orient.roll, wm->orient.a_roll);
|
||||||
|
printf("wiimote pitch = %f [%f]\n", wm->orient.pitch, wm->orient.a_pitch);
|
||||||
|
printf("wiimote yaw = %f\n", wm->orient.yaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If IR tracking is enabled then print the coordinates
|
||||||
|
* on the virtual screen that the wiimote is pointing to.
|
||||||
|
*
|
||||||
|
* Also make sure that we see at least 1 dot.
|
||||||
|
*/
|
||||||
|
if (WIIUSE_USING_IR(wm)) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
/* go through each of the 4 possible IR sources */
|
||||||
|
for (; i < 4; ++i) {
|
||||||
|
/* check if the source is visible */
|
||||||
|
if (wm->ir.dot[i].visible)
|
||||||
|
printf("IR source %i: (%u, %u)\n", i, wm->ir.dot[i].x, wm->ir.dot[i].y);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("IR cursor: (%u, %u)\n", wm->ir.x, wm->ir.y);
|
||||||
|
printf("IR z distance: %f\n", wm->ir.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* show events specific to supported expansions */
|
||||||
|
if (wm->exp.type == EXP_NUNCHUK) {
|
||||||
|
/* nunchuk */
|
||||||
|
struct nunchuk_t* nc = (nunchuk_t*)&wm->exp.nunchuk;
|
||||||
|
|
||||||
|
if (IS_PRESSED(nc, NUNCHUK_BUTTON_C)) printf("Nunchuk: C pressed\n");
|
||||||
|
if (IS_PRESSED(nc, NUNCHUK_BUTTON_Z)) printf("Nunchuk: Z pressed\n");
|
||||||
|
|
||||||
|
printf("nunchuk roll = %f\n", nc->orient.roll);
|
||||||
|
printf("nunchuk pitch = %f\n", nc->orient.pitch);
|
||||||
|
printf("nunchuk yaw = %f\n", nc->orient.yaw);
|
||||||
|
|
||||||
|
printf("nunchuk joystick angle: %f\n", nc->js.ang);
|
||||||
|
printf("nunchuk joystick magnitude: %f\n", nc->js.mag);
|
||||||
|
} else if (wm->exp.type == EXP_CLASSIC) {
|
||||||
|
/* classic controller */
|
||||||
|
struct classic_ctrl_t* cc = (classic_ctrl_t*)&wm->exp.classic;
|
||||||
|
|
||||||
|
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_ZL)) printf("Classic: ZL pressed\n");
|
||||||
|
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_B)) printf("Classic: B pressed\n");
|
||||||
|
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_Y)) printf("Classic: Y pressed\n");
|
||||||
|
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_A)) printf("Classic: A pressed\n");
|
||||||
|
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_X)) printf("Classic: X pressed\n");
|
||||||
|
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_ZR)) printf("Classic: ZR pressed\n");
|
||||||
|
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_LEFT)) printf("Classic: LEFT pressed\n");
|
||||||
|
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_UP)) printf("Classic: UP pressed\n");
|
||||||
|
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_RIGHT)) printf("Classic: RIGHT pressed\n");
|
||||||
|
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_DOWN)) printf("Classic: DOWN pressed\n");
|
||||||
|
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_FULL_L)) printf("Classic: FULL L pressed\n");
|
||||||
|
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_MINUS)) printf("Classic: MINUS pressed\n");
|
||||||
|
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_HOME)) printf("Classic: HOME pressed\n");
|
||||||
|
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_PLUS)) printf("Classic: PLUS pressed\n");
|
||||||
|
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_FULL_R)) printf("Classic: FULL R pressed\n");
|
||||||
|
|
||||||
|
printf("classic L button pressed: %f\n", cc->l_shoulder);
|
||||||
|
printf("classic R button pressed: %f\n", cc->r_shoulder);
|
||||||
|
printf("classic left joystick angle: %f\n", cc->ljs.ang);
|
||||||
|
printf("classic left joystick magnitude: %f\n", cc->ljs.mag);
|
||||||
|
printf("classic right joystick angle: %f\n", cc->rjs.ang);
|
||||||
|
printf("classic right joystick magnitude: %f\n", cc->rjs.mag);
|
||||||
|
} else if (wm->exp.type == EXP_GUITAR_HERO_3) {
|
||||||
|
/* guitar hero 3 guitar */
|
||||||
|
struct guitar_hero_3_t* gh3 = (guitar_hero_3_t*)&wm->exp.gh3;
|
||||||
|
|
||||||
|
if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_STRUM_UP)) printf("Guitar: Strum Up pressed\n");
|
||||||
|
if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_STRUM_DOWN)) printf("Guitar: Strum Down pressed\n");
|
||||||
|
if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_YELLOW)) printf("Guitar: Yellow pressed\n");
|
||||||
|
if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_GREEN)) printf("Guitar: Green pressed\n");
|
||||||
|
if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_BLUE)) printf("Guitar: Blue pressed\n");
|
||||||
|
if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_RED)) printf("Guitar: Red pressed\n");
|
||||||
|
if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_ORANGE)) printf("Guitar: Orange pressed\n");
|
||||||
|
if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_PLUS)) printf("Guitar: Plus pressed\n");
|
||||||
|
if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_MINUS)) printf("Guitar: Minus pressed\n");
|
||||||
|
|
||||||
|
printf("Guitar whammy bar: %f\n", gh3->whammy_bar);
|
||||||
|
printf("Guitar joystick angle: %f\n", gh3->js.ang);
|
||||||
|
printf("Guitar joystick magnitude: %f\n", gh3->js.mag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback that handles a read event.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param data Pointer to the filled data block.
|
||||||
|
* @param len Length in bytes of the data block.
|
||||||
|
*
|
||||||
|
* This function is called automatically by the wiiuse library when
|
||||||
|
* the wiimote has returned the full data requested by a previous
|
||||||
|
* call to wiiuse_read_data().
|
||||||
|
*
|
||||||
|
* You can read data on the wiimote, such as Mii data, if
|
||||||
|
* you know the offset address and the length.
|
||||||
|
*
|
||||||
|
* The \a data pointer was specified on the call to wiiuse_read_data().
|
||||||
|
* At the time of this function being called, it is not safe to deallocate
|
||||||
|
* this buffer.
|
||||||
|
*/
|
||||||
|
void handle_read(struct wiimote_t* wm, byte* data, unsigned short len) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
printf("\n\n--- DATA READ [wiimote id %i] ---\n", wm->unid);
|
||||||
|
printf("finished read of size %i\n", len);
|
||||||
|
for (; i < len; ++i) {
|
||||||
|
if (!(i%16))
|
||||||
|
printf("\n");
|
||||||
|
printf("%x ", data[i]);
|
||||||
|
}
|
||||||
|
printf("\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback that handles a controller status event.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param attachment Is there an attachment? (1 for yes, 0 for no)
|
||||||
|
* @param speaker Is the speaker enabled? (1 for yes, 0 for no)
|
||||||
|
* @param ir Is the IR support enabled? (1 for yes, 0 for no)
|
||||||
|
* @param led What LEDs are lit.
|
||||||
|
* @param battery_level Battery level, between 0.0 (0%) and 1.0 (100%).
|
||||||
|
*
|
||||||
|
* This occurs when either the controller status changed
|
||||||
|
* or the controller status was requested explicitly by
|
||||||
|
* wiiuse_status().
|
||||||
|
*
|
||||||
|
* One reason the status can change is if the nunchuk was
|
||||||
|
* inserted or removed from the expansion port.
|
||||||
|
*/
|
||||||
|
void handle_ctrl_status(struct wiimote_t* wm) {
|
||||||
|
printf("\n\n--- CONTROLLER STATUS [wiimote id %i] ---\n", wm->unid);
|
||||||
|
|
||||||
|
printf("attachment: %i\n", wm->exp.type);
|
||||||
|
printf("speaker: %i\n", WIIUSE_USING_SPEAKER(wm));
|
||||||
|
printf("ir: %i\n", WIIUSE_USING_IR(wm));
|
||||||
|
printf("leds: %i %i %i %i\n", WIIUSE_IS_LED_SET(wm, 1), WIIUSE_IS_LED_SET(wm, 2), WIIUSE_IS_LED_SET(wm, 3), WIIUSE_IS_LED_SET(wm, 4));
|
||||||
|
printf("battery: %f %%\n", wm->battery_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback that handles a disconnection event.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
*
|
||||||
|
* This can happen if the POWER button is pressed, or
|
||||||
|
* if the connection is interrupted.
|
||||||
|
*/
|
||||||
|
void handle_disconnect(wiimote* wm) {
|
||||||
|
printf("\n\n--- DISCONNECTED [wiimote id %i] ---\n", wm->unid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void test(struct wiimote_t* wm, byte* data, unsigned short len) {
|
||||||
|
printf("test: %i [%x %x %x %x]\n", len, data[0], data[1], data[2], data[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief main()
|
||||||
|
*
|
||||||
|
* Connect to up to two wiimotes and print any events
|
||||||
|
* that occur on either device.
|
||||||
|
*/
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
wiimote** wiimotes;
|
||||||
|
int found, connected;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize an array of wiimote objects.
|
||||||
|
*
|
||||||
|
* The parameter is the number of wiimotes I want to create.
|
||||||
|
*/
|
||||||
|
wiimotes = wiiuse_init(MAX_WIIMOTES);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find wiimote devices
|
||||||
|
*
|
||||||
|
* Now we need to find some wiimotes.
|
||||||
|
* Give the function the wiimote array we created, and tell it there
|
||||||
|
* are MAX_WIIMOTES wiimotes we are interested in.
|
||||||
|
*
|
||||||
|
* Set the timeout to be 5 seconds.
|
||||||
|
*
|
||||||
|
* This will return the number of actual wiimotes that are in discovery mode.
|
||||||
|
*/
|
||||||
|
found = wiiuse_find(wiimotes, MAX_WIIMOTES, 5);
|
||||||
|
if (!found) {
|
||||||
|
printf ("No wiimotes found.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Connect to the wiimotes
|
||||||
|
*
|
||||||
|
* Now that we found some wiimotes, connect to them.
|
||||||
|
* Give the function the wiimote array and the number
|
||||||
|
* of wiimote devices we found.
|
||||||
|
*
|
||||||
|
* This will return the number of established connections to the found wiimotes.
|
||||||
|
*/
|
||||||
|
connected = wiiuse_connect(wiimotes, MAX_WIIMOTES);
|
||||||
|
if (connected)
|
||||||
|
printf("Connected to %i wiimotes (of %i found).\n", connected, found);
|
||||||
|
else {
|
||||||
|
printf("Failed to connect to any wiimote.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now set the LEDs and rumble for a second so it's easy
|
||||||
|
* to tell which wiimotes are connected (just like the wii does).
|
||||||
|
*/
|
||||||
|
wiiuse_set_leds(wiimotes[0], WIIMOTE_LED_1);
|
||||||
|
wiiuse_set_leds(wiimotes[1], WIIMOTE_LED_2);
|
||||||
|
wiiuse_set_leds(wiimotes[2], WIIMOTE_LED_3);
|
||||||
|
wiiuse_set_leds(wiimotes[3], WIIMOTE_LED_4);
|
||||||
|
wiiuse_rumble(wiimotes[0], 1);
|
||||||
|
wiiuse_rumble(wiimotes[1], 1);
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
usleep(200000);
|
||||||
|
#else
|
||||||
|
Sleep(200);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wiiuse_rumble(wiimotes[0], 0);
|
||||||
|
wiiuse_rumble(wiimotes[1], 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maybe I'm interested in the battery power of the 0th
|
||||||
|
* wiimote. This should be WIIMOTE_ID_1 but to be sure
|
||||||
|
* you can get the wiimote assoicated with WIIMOTE_ID_1
|
||||||
|
* using the wiiuse_get_by_id() function.
|
||||||
|
*
|
||||||
|
* A status request will return other things too, like
|
||||||
|
* if any expansions are plugged into the wiimote or
|
||||||
|
* what LEDs are lit.
|
||||||
|
*/
|
||||||
|
//wiiuse_status(wiimotes[0]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the main loop
|
||||||
|
*
|
||||||
|
* wiiuse_poll() needs to be called with the wiimote array
|
||||||
|
* and the number of wiimote structures in that array
|
||||||
|
* (it doesn't matter if some of those wiimotes are not used
|
||||||
|
* or are not connected).
|
||||||
|
*
|
||||||
|
* This function will set the event flag for each wiimote
|
||||||
|
* when the wiimote has things to report.
|
||||||
|
*/
|
||||||
|
while (1) {
|
||||||
|
if (wiiuse_poll(wiimotes, MAX_WIIMOTES)) {
|
||||||
|
/*
|
||||||
|
* This happens if something happened on any wiimote.
|
||||||
|
* So go through each one and check if anything happened.
|
||||||
|
*/
|
||||||
|
int i = 0;
|
||||||
|
for (; i < MAX_WIIMOTES; ++i) {
|
||||||
|
switch (wiimotes[i]->event) {
|
||||||
|
case WIIUSE_EVENT:
|
||||||
|
/* a generic event occured */
|
||||||
|
handle_event(wiimotes[i]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WIIUSE_STATUS:
|
||||||
|
/* a status event occured */
|
||||||
|
handle_ctrl_status(wiimotes[i]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WIIUSE_DISCONNECT:
|
||||||
|
case WIIUSE_UNEXPECTED_DISCONNECT:
|
||||||
|
/* the wiimote disconnected */
|
||||||
|
handle_disconnect(wiimotes[i]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WIIUSE_READ_DATA:
|
||||||
|
/*
|
||||||
|
* Data we requested to read was returned.
|
||||||
|
* Take a look at wiimotes[i]->read_req
|
||||||
|
* for the data.
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WIIUSE_NUNCHUK_INSERTED:
|
||||||
|
/*
|
||||||
|
* a nunchuk was inserted
|
||||||
|
* This is a good place to set any nunchuk specific
|
||||||
|
* threshold values. By default they are the same
|
||||||
|
* as the wiimote.
|
||||||
|
*/
|
||||||
|
//wiiuse_set_nunchuk_orient_threshold((struct nunchuk_t*)&wiimotes[i]->exp.nunchuk, 90.0f);
|
||||||
|
//wiiuse_set_nunchuk_accel_threshold((struct nunchuk_t*)&wiimotes[i]->exp.nunchuk, 100);
|
||||||
|
printf("Nunchuk inserted.\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WIIUSE_CLASSIC_CTRL_INSERTED:
|
||||||
|
printf("Classic controller inserted.\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WIIUSE_GUITAR_HERO_3_CTRL_INSERTED:
|
||||||
|
/* some expansion was inserted */
|
||||||
|
handle_ctrl_status(wiimotes[i]);
|
||||||
|
printf("Guitar Hero 3 controller inserted.\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WIIUSE_NUNCHUK_REMOVED:
|
||||||
|
case WIIUSE_CLASSIC_CTRL_REMOVED:
|
||||||
|
case WIIUSE_GUITAR_HERO_3_CTRL_REMOVED:
|
||||||
|
/* some expansion was removed */
|
||||||
|
handle_ctrl_status(wiimotes[i]);
|
||||||
|
printf("An expansion was removed.\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disconnect the wiimotes
|
||||||
|
*/
|
||||||
|
wiiuse_cleanup(wiimotes, MAX_WIIMOTES);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
106
example/msvc/wiiuseexample.dsp
Normal file
106
example/msvc/wiiuseexample.dsp
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
# Microsoft Developer Studio Project File - Name="wiiuseexample" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||||
|
|
||||||
|
CFG=wiiuseexample - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "wiiuseexample.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "wiiuseexample.mak" CFG="wiiuseexample - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "wiiuseexample - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE "wiiuseexample - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "wiiuseexample - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /W3 /GX /O2 /I "..\..\src" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib wiiuse.lib /nologo /subsystem:console /machine:I386
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "wiiuseexample - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "wiiuseexample - Win32 Release"
|
||||||
|
# Name "wiiuseexample - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\example.c
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\src\wiiuse.h
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Resource Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
||||||
29
example/msvc/wiiuseexample.dsw
Normal file
29
example/msvc/wiiuseexample.dsw
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||||
|
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "wiiuseexample"=".\wiiuseexample.dsp" - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Global:
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<3>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
BIN
example/msvc/wiiuseexample.ncb
Normal file
BIN
example/msvc/wiiuseexample.ncb
Normal file
Binary file not shown.
BIN
example/msvc/wiiuseexample.opt
Normal file
BIN
example/msvc/wiiuseexample.opt
Normal file
Binary file not shown.
91
src/Makefile
Normal file
91
src/Makefile
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
#
|
||||||
|
# wiiuse Makefile
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Change this to your GCC version.
|
||||||
|
#
|
||||||
|
CC = gcc
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
#
|
||||||
|
# You should not need to edit below this line.
|
||||||
|
#
|
||||||
|
####################################################
|
||||||
|
|
||||||
|
#
|
||||||
|
# Universal cflags
|
||||||
|
#
|
||||||
|
CFLAGS = -Wall -pipe -fPIC -funroll-loops
|
||||||
|
|
||||||
|
ifeq ($(debug),1)
|
||||||
|
OBJ_PREFIX = debug
|
||||||
|
CFLAGS += -g -pg -DWITH_WIIUSE_DEBUG
|
||||||
|
|
||||||
|
else
|
||||||
|
OBJ_PREFIX = release
|
||||||
|
CFLAGS += -O2
|
||||||
|
endif
|
||||||
|
|
||||||
|
OBJ_DIR = $(OBJ_PREFIX)-$(shell $(CC) -v 2>&1|grep ^Target:|cut -d' ' -f2)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Linking flags
|
||||||
|
#
|
||||||
|
LDFLAGS = -shared -lm -lbluetooth
|
||||||
|
|
||||||
|
#
|
||||||
|
# Target binaries (always created as BIN)
|
||||||
|
#
|
||||||
|
BIN = ./$(OBJ_DIR)/libwiiuse.so
|
||||||
|
|
||||||
|
#
|
||||||
|
# Inclusion paths.
|
||||||
|
#
|
||||||
|
INCLUDES = -I.
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate a list of object files
|
||||||
|
#
|
||||||
|
OBJS = \
|
||||||
|
$(OBJ_DIR)/classic.o \
|
||||||
|
$(OBJ_DIR)/dynamics.o \
|
||||||
|
$(OBJ_DIR)/events.o \
|
||||||
|
$(OBJ_DIR)/io.o \
|
||||||
|
$(OBJ_DIR)/io_nix.o \
|
||||||
|
$(OBJ_DIR)/ir.o \
|
||||||
|
$(OBJ_DIR)/nunchuk.o \
|
||||||
|
$(OBJ_DIR)/guitar_hero_3.o \
|
||||||
|
$(OBJ_DIR)/wiiuse.o
|
||||||
|
|
||||||
|
###############################
|
||||||
|
#
|
||||||
|
# Build targets.
|
||||||
|
#
|
||||||
|
###############################
|
||||||
|
|
||||||
|
all: $(BIN)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@-rm $(OBJS) 2> /dev/null
|
||||||
|
|
||||||
|
distclean:
|
||||||
|
@-rm -r debug-* release-* 2> /dev/null
|
||||||
|
|
||||||
|
install:
|
||||||
|
@if [ -e $(BIN) ]; then \
|
||||||
|
cp -v $(BIN) /usr/lib ; \
|
||||||
|
fi
|
||||||
|
@cp -v wiiuse.h /usr/include
|
||||||
|
|
||||||
|
$(BIN): mkdir $(OBJS)
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(BIN)
|
||||||
|
|
||||||
|
$(OBJ_DIR)/%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
|
||||||
|
|
||||||
|
mkdir:
|
||||||
|
@if [ ! -d $(OBJ_DIR) ]; then \
|
||||||
|
mkdir $(OBJ_DIR); \
|
||||||
|
fi
|
||||||
|
|
||||||
190
src/classic.c
Normal file
190
src/classic.c
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Classic controller expansion device.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <Winsock2.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "definitions.h"
|
||||||
|
#include "wiiuse_internal.h"
|
||||||
|
#include "dynamics.h"
|
||||||
|
#include "events.h"
|
||||||
|
#include "classic.h"
|
||||||
|
|
||||||
|
static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle the handshake data from the classic controller.
|
||||||
|
*
|
||||||
|
* @param cc A pointer to a classic_ctrl_t structure.
|
||||||
|
* @param data The data read in from the device.
|
||||||
|
* @param len The length of the data block, in bytes.
|
||||||
|
*
|
||||||
|
* @return Returns 1 if handshake was successful, 0 if not.
|
||||||
|
*/
|
||||||
|
int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, byte* data, unsigned short len) {
|
||||||
|
int i;
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
cc->btns = 0;
|
||||||
|
cc->btns_held = 0;
|
||||||
|
cc->btns_released = 0;
|
||||||
|
cc->r_shoulder = 0;
|
||||||
|
cc->l_shoulder = 0;
|
||||||
|
|
||||||
|
/* decrypt data */
|
||||||
|
for (i = 0; i < len; ++i)
|
||||||
|
data[i] = (data[i] ^ 0x17) + 0x17;
|
||||||
|
|
||||||
|
if (data[offset] == 0xFF) {
|
||||||
|
/*
|
||||||
|
* Sometimes the data returned here is not correct.
|
||||||
|
* This might happen because the wiimote is lagging
|
||||||
|
* behind our initialization sequence.
|
||||||
|
* To fix this just request the handshake again.
|
||||||
|
*
|
||||||
|
* Other times it's just the first 16 bytes are 0xFF,
|
||||||
|
* but since the next 16 bytes are the same, just use
|
||||||
|
* those.
|
||||||
|
*/
|
||||||
|
if (data[offset + 16] == 0xFF) {
|
||||||
|
/* get the calibration data */
|
||||||
|
byte* handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
|
||||||
|
|
||||||
|
WIIUSE_DEBUG("Classic controller handshake appears invalid, trying again.");
|
||||||
|
wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
offset += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* joystick stuff */
|
||||||
|
cc->ljs.max.x = data[0 + offset] / 4;
|
||||||
|
cc->ljs.min.x = data[1 + offset] / 4;
|
||||||
|
cc->ljs.center.x = data[2 + offset] / 4;
|
||||||
|
cc->ljs.max.y = data[3 + offset] / 4;
|
||||||
|
cc->ljs.min.y = data[4 + offset] / 4;
|
||||||
|
cc->ljs.center.y = data[5 + offset] / 4;
|
||||||
|
|
||||||
|
cc->rjs.max.x = data[6 + offset] / 8;
|
||||||
|
cc->rjs.min.x = data[7 + offset] / 8;
|
||||||
|
cc->rjs.center.x = data[8 + offset] / 8;
|
||||||
|
cc->rjs.max.y = data[9 + offset] / 8;
|
||||||
|
cc->rjs.min.y = data[10 + offset] / 8;
|
||||||
|
cc->rjs.center.y = data[11 + offset] / 8;
|
||||||
|
|
||||||
|
/* handshake done */
|
||||||
|
wm->exp.type = EXP_CLASSIC;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The classic controller disconnected.
|
||||||
|
*
|
||||||
|
* @param cc A pointer to a classic_ctrl_t structure.
|
||||||
|
*/
|
||||||
|
void classic_ctrl_disconnected(struct classic_ctrl_t* cc) {
|
||||||
|
memset(cc, 0, sizeof(struct classic_ctrl_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle classic controller event.
|
||||||
|
*
|
||||||
|
* @param cc A pointer to a classic_ctrl_t structure.
|
||||||
|
* @param msg The message specified in the event packet.
|
||||||
|
*/
|
||||||
|
void classic_ctrl_event(struct classic_ctrl_t* cc, byte* msg) {
|
||||||
|
int i, lx, ly, rx, ry;
|
||||||
|
byte l, r;
|
||||||
|
|
||||||
|
/* decrypt data */
|
||||||
|
for (i = 0; i < 6; ++i)
|
||||||
|
msg[i] = (msg[i] ^ 0x17) + 0x17;
|
||||||
|
|
||||||
|
classic_ctrl_pressed_buttons(cc, BIG_ENDIAN_SHORT(*(short*)(msg + 4)));
|
||||||
|
|
||||||
|
/* left/right buttons */
|
||||||
|
l = (((msg[2] & 0x60) >> 2) | ((msg[3] & 0xE0) >> 5));
|
||||||
|
r = (msg[3] & 0x1F);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO - LR range hardcoded from 0x00 to 0x1F.
|
||||||
|
* This is probably in the calibration somewhere.
|
||||||
|
*/
|
||||||
|
cc->r_shoulder = ((float)r / 0x1F);
|
||||||
|
cc->l_shoulder = ((float)l / 0x1F);
|
||||||
|
|
||||||
|
/* calculate joystick orientation */
|
||||||
|
lx = (msg[0] & 0x3F);
|
||||||
|
ly = (msg[1] & 0x3F);
|
||||||
|
rx = ((msg[0] & 0xC0) >> 3) | ((msg[1] & 0xC0) >> 5) | ((msg[2] & 0x80) >> 7);
|
||||||
|
ry = (msg[2] & 0x1F);
|
||||||
|
|
||||||
|
calc_joystick_state(&cc->ljs, lx, ly);
|
||||||
|
calc_joystick_state(&cc->rjs, rx, ry);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Find what buttons are pressed.
|
||||||
|
*
|
||||||
|
* @param cc A pointer to a classic_ctrl_t structure.
|
||||||
|
* @param msg The message byte specified in the event packet.
|
||||||
|
*/
|
||||||
|
static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now) {
|
||||||
|
/* message is inverted (0 is active, 1 is inactive) */
|
||||||
|
now = ~now & CLASSIC_CTRL_BUTTON_ALL;
|
||||||
|
|
||||||
|
/* pressed now & were pressed, then held */
|
||||||
|
cc->btns_held = (now & cc->btns);
|
||||||
|
|
||||||
|
/* were pressed or were held & not pressed now, then released */
|
||||||
|
cc->btns_released = ((cc->btns | cc->btns_held) & ~now);
|
||||||
|
|
||||||
|
/* buttons pressed now */
|
||||||
|
cc->btns = now;
|
||||||
|
}
|
||||||
53
src/classic.h
Normal file
53
src/classic.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Classic controller expansion device.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CLASSIC_H_INCLUDED
|
||||||
|
#define CLASSIC_H_INCLUDED
|
||||||
|
|
||||||
|
#include "wiiuse_internal.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, byte* data, unsigned short len);
|
||||||
|
|
||||||
|
void classic_ctrl_disconnected(struct classic_ctrl_t* cc);
|
||||||
|
|
||||||
|
void classic_ctrl_event(struct classic_ctrl_t* cc, byte* msg);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // CLASSIC_H_INCLUDED
|
||||||
79
src/definitions.h
Normal file
79
src/definitions.h
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief General definitions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DEFINITIONS_H_INCLUDED
|
||||||
|
#define DEFINITIONS_H_INCLUDED
|
||||||
|
|
||||||
|
/* this is wiiuse - used to distinguish from third party programs using wiiuse.h */
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
|
#define WIIMOTE_PI 3.14159265f
|
||||||
|
|
||||||
|
//#define WITH_WIIUSE_DEBUG
|
||||||
|
|
||||||
|
/* Error output macros */
|
||||||
|
#define WIIUSE_ERROR(fmt, ...) fprintf(stderr, "[ERROR] " fmt "\n", ##__VA_ARGS__)
|
||||||
|
|
||||||
|
/* Warning output macros */
|
||||||
|
#define WIIUSE_WARNING(fmt, ...) fprintf(stderr, "[WARNING] " fmt "\n", ##__VA_ARGS__)
|
||||||
|
|
||||||
|
/* Information output macros */
|
||||||
|
#define WIIUSE_INFO(fmt, ...) fprintf(stderr, "[INFO] " fmt "\n", ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#ifdef WITH_WIIUSE_DEBUG
|
||||||
|
#ifdef WIN32
|
||||||
|
#define WIIUSE_DEBUG(fmt, ...) do { \
|
||||||
|
char* file = __FILE__; \
|
||||||
|
int i = strlen(file) - 1; \
|
||||||
|
for (; i && (file[i] != '\\'); --i); \
|
||||||
|
fprintf(stderr, "[DEBUG] %s:%i: " fmt "\n", file+i+1, __LINE__, ##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define WIIUSE_DEBUG(fmt, ...) fprintf(stderr, "[DEBUG] " __FILE__ ":%i: " fmt "\n", __LINE__, ##__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define WIIUSE_DEBUG(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Convert between radians and degrees */
|
||||||
|
#define RAD_TO_DEGREE(r) ((r * 180.0f) / WIIMOTE_PI)
|
||||||
|
#define DEGREE_TO_RAD(d) (d * (WIIMOTE_PI / 180.0f))
|
||||||
|
|
||||||
|
/* Convert to big endian */
|
||||||
|
#define BIG_ENDIAN_LONG(i) (htonl(i))
|
||||||
|
#define BIG_ENDIAN_SHORT(i) (htons(i))
|
||||||
|
|
||||||
|
#define absf(x) ((x >= 0) ? (x) : (x * -1.0f))
|
||||||
|
#define diff_f(x, y) ((x >= y) ? (absf(x - y)) : (absf(y - x)))
|
||||||
|
|
||||||
|
#endif // DEFINITIONS_H_INCLUDED
|
||||||
228
src/dynamics.c
Normal file
228
src/dynamics.c
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Handles the dynamics of the wiimote.
|
||||||
|
*
|
||||||
|
* The file includes functions that handle the dynamics
|
||||||
|
* of the wiimote. Such dynamics include orientation and
|
||||||
|
* motion sensing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <float.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "definitions.h"
|
||||||
|
#include "wiiuse_internal.h"
|
||||||
|
#include "ir.h"
|
||||||
|
#include "dynamics.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate the roll, pitch, yaw.
|
||||||
|
*
|
||||||
|
* @param ac An accelerometer (accel_t) structure.
|
||||||
|
* @param accel [in] Pointer to a vec3b_t structure that holds the raw acceleration data.
|
||||||
|
* @param orient [out] Pointer to a orient_t structure that will hold the orientation data.
|
||||||
|
* @param rorient [out] Pointer to a orient_t structure that will hold the non-smoothed orientation data.
|
||||||
|
* @param smooth If smoothing should be performed on the angles calculated. 1 to enable, 0 to disable.
|
||||||
|
*
|
||||||
|
* Given the raw acceleration data from the accelerometer struct, calculate
|
||||||
|
* the orientation of the device and set it in the \a orient parameter.
|
||||||
|
*/
|
||||||
|
void calculate_orientation(struct accel_t* ac, struct vec3b_t* accel, struct orient_t* orient, int smooth) {
|
||||||
|
float xg, yg, zg;
|
||||||
|
float x, y, z;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* roll - use atan(z / x) [ ranges from -180 to 180 ]
|
||||||
|
* pitch - use atan(z / y) [ ranges from -180 to 180 ]
|
||||||
|
* yaw - impossible to tell without IR
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* yaw - set to 0, IR will take care of it if it's enabled */
|
||||||
|
orient->yaw = 0.0f;
|
||||||
|
|
||||||
|
/* find out how much it has to move to be 1g */
|
||||||
|
xg = (float)ac->cal_g.x;
|
||||||
|
yg = (float)ac->cal_g.y;
|
||||||
|
zg = (float)ac->cal_g.z;
|
||||||
|
|
||||||
|
/* find out how much it actually moved and normalize to +/- 1g */
|
||||||
|
x = ((float)accel->x - (float)ac->cal_zero.x) / xg;
|
||||||
|
y = ((float)accel->y - (float)ac->cal_zero.y) / yg;
|
||||||
|
z = ((float)accel->z - (float)ac->cal_zero.z) / zg;
|
||||||
|
|
||||||
|
/* make sure x,y,z are between -1 and 1 for the tan functions */
|
||||||
|
if (x < -1.0f) x = -1.0f;
|
||||||
|
else if (x > 1.0f) x = 1.0f;
|
||||||
|
if (y < -1.0f) y = -1.0f;
|
||||||
|
else if (y > 1.0f) y = 1.0f;
|
||||||
|
if (z < -1.0f) z = -1.0f;
|
||||||
|
else if (z > 1.0f) z = 1.0f;
|
||||||
|
|
||||||
|
/* if it is over 1g then it is probably accelerating and not reliable */
|
||||||
|
if (abs(accel->x - ac->cal_zero.x) <= ac->cal_g.x) {
|
||||||
|
/* roll */
|
||||||
|
x = RAD_TO_DEGREE(atan2f(x, z));
|
||||||
|
|
||||||
|
orient->roll = x;
|
||||||
|
orient->a_roll = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (abs(accel->y - ac->cal_zero.y) <= ac->cal_g.y) {
|
||||||
|
/* pitch */
|
||||||
|
y = RAD_TO_DEGREE(atan2f(y, z));
|
||||||
|
|
||||||
|
orient->pitch = y;
|
||||||
|
orient->a_pitch = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* smooth the angles if enabled */
|
||||||
|
if (smooth) {
|
||||||
|
apply_smoothing(ac, orient, SMOOTH_ROLL);
|
||||||
|
apply_smoothing(ac, orient, SMOOTH_PITCH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate the gravity forces on each axis.
|
||||||
|
*
|
||||||
|
* @param ac An accelerometer (accel_t) structure.
|
||||||
|
* @param accel [in] Pointer to a vec3b_t structure that holds the raw acceleration data.
|
||||||
|
* @param gforce [out] Pointer to a gforce_t structure that will hold the gravity force data.
|
||||||
|
*/
|
||||||
|
void calculate_gforce(struct accel_t* ac, struct vec3b_t* accel, struct gforce_t* gforce) {
|
||||||
|
float xg, yg, zg;
|
||||||
|
|
||||||
|
/* find out how much it has to move to be 1g */
|
||||||
|
xg = (float)ac->cal_g.x;
|
||||||
|
yg = (float)ac->cal_g.y;
|
||||||
|
zg = (float)ac->cal_g.z;
|
||||||
|
|
||||||
|
/* find out how much it actually moved and normalize to +/- 1g */
|
||||||
|
gforce->x = ((float)accel->x - (float)ac->cal_zero.x) / xg;
|
||||||
|
gforce->y = ((float)accel->y - (float)ac->cal_zero.y) / yg;
|
||||||
|
gforce->z = ((float)accel->z - (float)ac->cal_zero.z) / zg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate the angle and magnitude of a joystick.
|
||||||
|
*
|
||||||
|
* @param js [out] Pointer to a joystick_t structure.
|
||||||
|
* @param x The raw x-axis value.
|
||||||
|
* @param y The raw y-axis value.
|
||||||
|
*/
|
||||||
|
void calc_joystick_state(struct joystick_t* js, float x, float y) {
|
||||||
|
float rx, ry, ang;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since the joystick center may not be exactly:
|
||||||
|
* (min + max) / 2
|
||||||
|
* Then the range from the min to the center and the center to the max
|
||||||
|
* may be different.
|
||||||
|
* Because of this, depending on if the current x or y value is greater
|
||||||
|
* or less than the assoicated axis center value, it needs to be interpolated
|
||||||
|
* between the center and the minimum or maxmimum rather than between
|
||||||
|
* the minimum and maximum.
|
||||||
|
*
|
||||||
|
* So we have something like this:
|
||||||
|
* (x min) [-1] ---------*------ [0] (x center) [0] -------- [1] (x max)
|
||||||
|
* Where the * is the current x value.
|
||||||
|
* The range is therefore -1 to 1, 0 being the exact center rather than
|
||||||
|
* the middle of min and max.
|
||||||
|
*/
|
||||||
|
if (x == js->center.x)
|
||||||
|
rx = 0;
|
||||||
|
else if (x >= js->center.x)
|
||||||
|
rx = ((float)(x - js->center.x) / (float)(js->max.x - js->center.x));
|
||||||
|
else
|
||||||
|
rx = ((float)(x - js->min.x) / (float)(js->center.x - js->min.x)) - 1.0f;
|
||||||
|
|
||||||
|
if (y == js->center.y)
|
||||||
|
ry = 0;
|
||||||
|
else if (y >= js->center.y)
|
||||||
|
ry = ((float)(y - js->center.y) / (float)(js->max.y - js->center.y));
|
||||||
|
else
|
||||||
|
ry = ((float)(y - js->min.y) / (float)(js->center.y - js->min.y)) - 1.0f;
|
||||||
|
|
||||||
|
/* calculate the joystick angle and magnitude */
|
||||||
|
ang = RAD_TO_DEGREE(atanf(ry / rx));
|
||||||
|
ang -= 90.0f;
|
||||||
|
if (rx < 0.0f)
|
||||||
|
ang -= 180.0f;
|
||||||
|
js->ang = absf(ang);
|
||||||
|
js->mag = (float) sqrt((rx * rx) + (ry * ry));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void apply_smoothing(struct accel_t* ac, struct orient_t* orient, int type) {
|
||||||
|
switch (type) {
|
||||||
|
case SMOOTH_ROLL:
|
||||||
|
{
|
||||||
|
/* it's possible last iteration was nan or inf, so set it to 0 if that happened */
|
||||||
|
if (isnan(ac->st_roll) || isinf(ac->st_roll))
|
||||||
|
ac->st_roll = 0.0f;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the sign changes (which will happen if going from -180 to 180)
|
||||||
|
* or from (-1 to 1) then don't smooth, just use the new angle.
|
||||||
|
*/
|
||||||
|
if (((ac->st_roll < 0) && (orient->roll > 0)) || ((ac->st_roll > 0) && (orient->roll < 0))) {
|
||||||
|
ac->st_roll = orient->roll;
|
||||||
|
} else {
|
||||||
|
orient->roll = ac->st_roll + (ac->st_alpha * (orient->a_roll - ac->st_roll));
|
||||||
|
ac->st_roll = orient->roll;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SMOOTH_PITCH:
|
||||||
|
{
|
||||||
|
if (isnan(ac->st_pitch) || isinf(ac->st_pitch))
|
||||||
|
ac->st_pitch = 0.0f;
|
||||||
|
|
||||||
|
if (((ac->st_pitch < 0) && (orient->pitch > 0)) || ((ac->st_pitch > 0) && (orient->pitch < 0))) {
|
||||||
|
ac->st_pitch = orient->pitch;
|
||||||
|
} else {
|
||||||
|
orient->pitch = ac->st_pitch + (ac->st_alpha * (orient->a_pitch - ac->st_pitch));
|
||||||
|
ac->st_pitch = orient->pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
56
src/dynamics.h
Normal file
56
src/dynamics.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Handles the dynamics of the wiimote.
|
||||||
|
*
|
||||||
|
* The file includes functions that handle the dynamics
|
||||||
|
* of the wiimote. Such dynamics include orientation and
|
||||||
|
* motion sensing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DYNAMICS_H_INCLUDED
|
||||||
|
#define DYNAMICS_H_INCLUDED
|
||||||
|
|
||||||
|
#include "wiiuse_internal.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void calculate_orientation(struct accel_t* ac, struct vec3b_t* accel, struct orient_t* orient, int smooth);
|
||||||
|
void calculate_gforce(struct accel_t* ac, struct vec3b_t* accel, struct gforce_t* gforce);
|
||||||
|
void calc_joystick_state(struct joystick_t* js, float x, float y);
|
||||||
|
void apply_smoothing(struct accel_t* ac, struct orient_t* orient, int type);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // DYNAMICS_H_INCLUDED
|
||||||
878
src/events.c
Normal file
878
src/events.c
Normal file
@@ -0,0 +1,878 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Handles wiimote events.
|
||||||
|
*
|
||||||
|
* The file includes functions that handle the events
|
||||||
|
* that are sent from the wiimote to us.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#else
|
||||||
|
#include <winsock2.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "definitions.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "wiiuse_internal.h"
|
||||||
|
#include "dynamics.h"
|
||||||
|
#include "ir.h"
|
||||||
|
#include "nunchuk.h"
|
||||||
|
#include "classic.h"
|
||||||
|
#include "guitar_hero_3.h"
|
||||||
|
#include "events.h"
|
||||||
|
|
||||||
|
static void idle_cycle(struct wiimote_t* wm);
|
||||||
|
static void clear_dirty_reads(struct wiimote_t* wm);
|
||||||
|
static void propagate_event(struct wiimote_t* wm, byte event, byte* msg);
|
||||||
|
static void event_data_read(struct wiimote_t* wm, byte* msg);
|
||||||
|
static void event_status(struct wiimote_t* wm, byte* msg);
|
||||||
|
static void handle_expansion(struct wiimote_t* wm, byte* msg);
|
||||||
|
|
||||||
|
static void save_state(struct wiimote_t* wm);
|
||||||
|
static int state_changed(struct wiimote_t* wm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Poll the wiimotes for any events.
|
||||||
|
*
|
||||||
|
* @param wm An array of pointers to wiimote_t structures.
|
||||||
|
* @param wiimotes The number of wiimote_t structures in the \a wm array.
|
||||||
|
*
|
||||||
|
* @return Returns number of wiimotes that an event has occured on.
|
||||||
|
*
|
||||||
|
* It is necessary to poll the wiimote devices for events
|
||||||
|
* that occur. If an event occurs on a particular wiimote,
|
||||||
|
* the event variable will be set.
|
||||||
|
*/
|
||||||
|
int wiiuse_poll(struct wiimote_t** wm, int wiimotes) {
|
||||||
|
int evnt = 0;
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
/*
|
||||||
|
* *nix
|
||||||
|
*/
|
||||||
|
struct timeval tv;
|
||||||
|
fd_set fds;
|
||||||
|
int r;
|
||||||
|
int i;
|
||||||
|
int highest_fd = -1;
|
||||||
|
|
||||||
|
if (!wm) return 0;
|
||||||
|
|
||||||
|
/* block select() for 1/2000th of a second */
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 500;
|
||||||
|
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
|
||||||
|
for (i = 0; i < wiimotes; ++i) {
|
||||||
|
/* only poll it if it is connected */
|
||||||
|
if (WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_CONNECTED)) {
|
||||||
|
FD_SET(wm[i]->in_sock, &fds);
|
||||||
|
|
||||||
|
/* find the highest fd of the connected wiimotes */
|
||||||
|
if (wm[i]->in_sock > highest_fd)
|
||||||
|
highest_fd = wm[i]->in_sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
wm[i]->event = WIIUSE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (highest_fd == -1)
|
||||||
|
/* nothing to poll */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (select(highest_fd + 1, &fds, NULL, NULL, &tv) == -1) {
|
||||||
|
WIIUSE_ERROR("Unable to select() the wiimote interrupt socket(s).");
|
||||||
|
perror("Error Details");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check each socket for an event */
|
||||||
|
for (i = 0; i < wiimotes; ++i) {
|
||||||
|
/* if this wiimote is not connected, skip it */
|
||||||
|
if (!WIIMOTE_IS_CONNECTED(wm[i]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (FD_ISSET(wm[i]->in_sock, &fds)) {
|
||||||
|
/* clear out the event buffer */
|
||||||
|
memset(wm[i]->event_buf, 0, sizeof(wm[i]->event_buf));
|
||||||
|
|
||||||
|
/* clear out any old read requests */
|
||||||
|
clear_dirty_reads(wm[i]);
|
||||||
|
|
||||||
|
/* read the pending message into the buffer */
|
||||||
|
r = read(wm[i]->in_sock, wm[i]->event_buf, sizeof(wm[i]->event_buf));
|
||||||
|
if (r == -1) {
|
||||||
|
/* error reading data */
|
||||||
|
WIIUSE_ERROR("Receiving wiimote data (id %i).", wm[i]->unid);
|
||||||
|
perror("Error Details");
|
||||||
|
|
||||||
|
if (errno == ENOTCONN) {
|
||||||
|
/* this can happen if the bluetooth dongle is disconnected */
|
||||||
|
WIIUSE_ERROR("Bluetooth appears to be disconnected. Wiimote unid %i will be disconnected.", wm[i]->unid);
|
||||||
|
wiiuse_disconnect(wm[i]);
|
||||||
|
wm[i]->event = WIIUSE_UNEXPECTED_DISCONNECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!r) {
|
||||||
|
/* remote disconnect */
|
||||||
|
wiiuse_disconnected(wm[i]);
|
||||||
|
evnt = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* propagate the event */
|
||||||
|
propagate_event(wm[i], wm[i]->event_buf[1], wm[i]->event_buf+2);
|
||||||
|
evnt += (wm[i]->event != WIIUSE_NONE);
|
||||||
|
} else {
|
||||||
|
idle_cycle(wm[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* Windows
|
||||||
|
*/
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!wm) return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < wiimotes; ++i) {
|
||||||
|
wm[i]->event = WIIUSE_NONE;
|
||||||
|
|
||||||
|
if (wiiuse_io_read(wm[i])) {
|
||||||
|
/* propagate the event */
|
||||||
|
propagate_event(wm[i], wm[i]->event_buf[0], wm[i]->event_buf+1);
|
||||||
|
evnt += (wm[i]->event != WIIUSE_NONE);
|
||||||
|
|
||||||
|
/* clear out the event buffer */
|
||||||
|
memset(wm[i]->event_buf, 0, sizeof(wm[i]->event_buf));
|
||||||
|
} else {
|
||||||
|
idle_cycle(wm[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return evnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called on a cycle where no significant change occurs.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
*/
|
||||||
|
static void idle_cycle(struct wiimote_t* wm) {
|
||||||
|
/*
|
||||||
|
* Smooth the angles.
|
||||||
|
*
|
||||||
|
* This is done to make sure that on every cycle the orientation
|
||||||
|
* angles are smoothed. Normally when an event occurs the angles
|
||||||
|
* are updated and smoothed, but if no packet comes in then the
|
||||||
|
* angles remain the same. This means the angle wiiuse reports
|
||||||
|
* is still an old value. Smoothing needs to be applied in this
|
||||||
|
* case in order for the angle it reports to converge to the true
|
||||||
|
* angle of the device.
|
||||||
|
*/
|
||||||
|
if (WIIUSE_USING_ACC(wm) && WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING)) {
|
||||||
|
apply_smoothing(&wm->accel_calib, &wm->orient, SMOOTH_ROLL);
|
||||||
|
apply_smoothing(&wm->accel_calib, &wm->orient, SMOOTH_PITCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clear out any old read requests */
|
||||||
|
clear_dirty_reads(wm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear out all old 'dirty' read requests.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
*/
|
||||||
|
static void clear_dirty_reads(struct wiimote_t* wm) {
|
||||||
|
struct read_req_t* req = wm->read_req;
|
||||||
|
|
||||||
|
while (req && req->dirty) {
|
||||||
|
WIIUSE_DEBUG("Cleared old read request for address: %x", req->addr);
|
||||||
|
|
||||||
|
wm->read_req = req->next;
|
||||||
|
free(req);
|
||||||
|
req = wm->read_req;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Analyze the event that occured on a wiimote.
|
||||||
|
*
|
||||||
|
* @param wm An array of pointers to wiimote_t structures.
|
||||||
|
* @param event The event that occured.
|
||||||
|
* @param msg The message specified in the event packet.
|
||||||
|
*
|
||||||
|
* Pass the event to the registered event callback.
|
||||||
|
*/
|
||||||
|
static void propagate_event(struct wiimote_t* wm, byte event, byte* msg) {
|
||||||
|
save_state(wm);
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case WM_RPT_BTN:
|
||||||
|
{
|
||||||
|
/* button */
|
||||||
|
wiiuse_pressed_buttons(wm, msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_RPT_BTN_ACC:
|
||||||
|
{
|
||||||
|
/* button - motion */
|
||||||
|
wiiuse_pressed_buttons(wm, msg);
|
||||||
|
|
||||||
|
wm->accel.x = msg[2];
|
||||||
|
wm->accel.y = msg[3];
|
||||||
|
wm->accel.z = msg[4];
|
||||||
|
|
||||||
|
/* calculate the remote orientation */
|
||||||
|
calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
|
||||||
|
|
||||||
|
/* calculate the gforces on each axis */
|
||||||
|
calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_RPT_READ:
|
||||||
|
{
|
||||||
|
/* data read */
|
||||||
|
event_data_read(wm, msg);
|
||||||
|
|
||||||
|
/* yeah buttons may be pressed, but this wasn't an "event" */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case WM_RPT_CTRL_STATUS:
|
||||||
|
{
|
||||||
|
/* controller status */
|
||||||
|
event_status(wm, msg);
|
||||||
|
|
||||||
|
/* don't execute the event callback */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case WM_RPT_BTN_EXP:
|
||||||
|
{
|
||||||
|
/* button - expansion */
|
||||||
|
wiiuse_pressed_buttons(wm, msg);
|
||||||
|
handle_expansion(wm, msg+2);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_RPT_BTN_ACC_EXP:
|
||||||
|
{
|
||||||
|
/* button - motion - expansion */
|
||||||
|
wiiuse_pressed_buttons(wm, msg);
|
||||||
|
|
||||||
|
wm->accel.x = msg[2];
|
||||||
|
wm->accel.y = msg[3];
|
||||||
|
wm->accel.z = msg[4];
|
||||||
|
|
||||||
|
calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
|
||||||
|
calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
|
||||||
|
|
||||||
|
handle_expansion(wm, msg+5);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_RPT_BTN_ACC_IR:
|
||||||
|
{
|
||||||
|
/* button - motion - ir */
|
||||||
|
wiiuse_pressed_buttons(wm, msg);
|
||||||
|
|
||||||
|
wm->accel.x = msg[2];
|
||||||
|
wm->accel.y = msg[3];
|
||||||
|
wm->accel.z = msg[4];
|
||||||
|
|
||||||
|
calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
|
||||||
|
calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
|
||||||
|
|
||||||
|
/* ir */
|
||||||
|
calculate_extended_ir(wm, msg+5);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_RPT_BTN_IR_EXP:
|
||||||
|
{
|
||||||
|
/* button - ir - expansion */
|
||||||
|
wiiuse_pressed_buttons(wm, msg);
|
||||||
|
handle_expansion(wm, msg+12);
|
||||||
|
|
||||||
|
/* ir */
|
||||||
|
calculate_basic_ir(wm, msg+2);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_RPT_BTN_ACC_IR_EXP:
|
||||||
|
{
|
||||||
|
/* button - motion - ir - expansion */
|
||||||
|
wiiuse_pressed_buttons(wm, msg);
|
||||||
|
|
||||||
|
wm->accel.x = msg[2];
|
||||||
|
wm->accel.y = msg[3];
|
||||||
|
wm->accel.z = msg[4];
|
||||||
|
|
||||||
|
calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
|
||||||
|
calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
|
||||||
|
|
||||||
|
handle_expansion(wm, msg+15);
|
||||||
|
|
||||||
|
/* ir */
|
||||||
|
calculate_basic_ir(wm, msg+5);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_RPT_WRITE:
|
||||||
|
{
|
||||||
|
/* write feedback - safe to skip */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
WIIUSE_WARNING("Unknown event, can not handle it [Code 0x%x].", event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* was there an event? */
|
||||||
|
if (state_changed(wm))
|
||||||
|
wm->event = WIIUSE_EVENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Find what buttons are pressed.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param msg The message specified in the event packet.
|
||||||
|
*/
|
||||||
|
void wiiuse_pressed_buttons(struct wiimote_t* wm, byte* msg) {
|
||||||
|
short now;
|
||||||
|
|
||||||
|
/* convert to big endian */
|
||||||
|
now = BIG_ENDIAN_SHORT(*(short*)msg) & WIIMOTE_BUTTON_ALL;
|
||||||
|
|
||||||
|
/* pressed now & were pressed, then held */
|
||||||
|
wm->btns_held = (now & wm->btns);
|
||||||
|
|
||||||
|
/* were pressed or were held & not pressed now, then released */
|
||||||
|
wm->btns_released = ((wm->btns | wm->btns_held) & ~now);
|
||||||
|
|
||||||
|
/* buttons pressed now */
|
||||||
|
wm->btns = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Received a data packet from a read request.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param msg The message specified in the event packet.
|
||||||
|
*
|
||||||
|
* Data from the wiimote comes in packets. If the requested
|
||||||
|
* data segment size is bigger than one packet can hold then
|
||||||
|
* several packets will be received. These packets are first
|
||||||
|
* reassembled into one, then the registered callback function
|
||||||
|
* that handles data reads is invoked.
|
||||||
|
*/
|
||||||
|
static void event_data_read(struct wiimote_t* wm, byte* msg) {
|
||||||
|
/* we must always assume the packet received is from the most recent request */
|
||||||
|
byte err;
|
||||||
|
byte len;
|
||||||
|
unsigned short offset;
|
||||||
|
struct read_req_t* req = wm->read_req;
|
||||||
|
|
||||||
|
wiiuse_pressed_buttons(wm, msg);
|
||||||
|
|
||||||
|
/* find the next non-dirty request */
|
||||||
|
while (req && req->dirty)
|
||||||
|
req = req->next;
|
||||||
|
|
||||||
|
/* if we don't have a request out then we didn't ask for this packet */
|
||||||
|
if (!req) {
|
||||||
|
WIIUSE_WARNING("Received data packet when no request was made.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = msg[2] & 0x0F;
|
||||||
|
|
||||||
|
if (err == 0x08)
|
||||||
|
WIIUSE_WARNING("Unable to read data - address does not exist.");
|
||||||
|
else if (err == 0x07)
|
||||||
|
WIIUSE_WARNING("Unable to read data - address is for write-only registers.");
|
||||||
|
else if (err)
|
||||||
|
WIIUSE_WARNING("Unable to read data - unknown error code %x.", err);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
/* this request errored out, so skip it and go to the next one */
|
||||||
|
|
||||||
|
/* delete this request */
|
||||||
|
wm->read_req = req->next;
|
||||||
|
free(req);
|
||||||
|
|
||||||
|
/* if another request exists send it to the wiimote */
|
||||||
|
if (wm->read_req)
|
||||||
|
wiiuse_send_next_pending_read_request(wm);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = ((msg[2] & 0xF0) >> 4) + 1;
|
||||||
|
offset = BIG_ENDIAN_SHORT(*(unsigned short*)(msg + 3));
|
||||||
|
req->addr = (req->addr & 0xFFFF);
|
||||||
|
|
||||||
|
req->wait -= len;
|
||||||
|
if (req->wait >= req->size)
|
||||||
|
/* this should never happen */
|
||||||
|
req->wait = 0;
|
||||||
|
|
||||||
|
WIIUSE_DEBUG("Received read packet:");
|
||||||
|
WIIUSE_DEBUG(" Packet read offset: %i bytes", offset);
|
||||||
|
WIIUSE_DEBUG(" Request read offset: %i bytes", req->addr);
|
||||||
|
WIIUSE_DEBUG(" Read offset into buf: %i bytes", offset - req->addr);
|
||||||
|
WIIUSE_DEBUG(" Read data size: %i bytes", len);
|
||||||
|
WIIUSE_DEBUG(" Still need: %i bytes", req->wait);
|
||||||
|
|
||||||
|
/* reconstruct this part of the data */
|
||||||
|
memcpy((req->buf + offset - req->addr), (msg + 5), len);
|
||||||
|
|
||||||
|
#ifdef WITH_WIIUSE_DEBUG
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
printf("Read: ");
|
||||||
|
for (; i < req->size - req->wait; ++i)
|
||||||
|
printf("%x ", req->buf[i]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* if all data has been received, execute the read event callback or generate event */
|
||||||
|
if (!req->wait) {
|
||||||
|
if (req->cb) {
|
||||||
|
/* this was a callback, so invoke it now */
|
||||||
|
req->cb(wm, req->buf, req->size);
|
||||||
|
|
||||||
|
/* delete this request */
|
||||||
|
wm->read_req = req->next;
|
||||||
|
free(req);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* This should generate an event.
|
||||||
|
* We need to leave the event in the array so the client
|
||||||
|
* can access it still. We'll flag is as being 'dirty'
|
||||||
|
* and give the client one cycle to use it. Next event
|
||||||
|
* we will remove it from the list.
|
||||||
|
*/
|
||||||
|
wm->event = WIIUSE_READ_DATA;
|
||||||
|
req->dirty = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if another request exists send it to the wiimote */
|
||||||
|
if (wm->read_req)
|
||||||
|
wiiuse_send_next_pending_read_request(wm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read the controller status.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param msg The message specified in the event packet.
|
||||||
|
*
|
||||||
|
* Read the controller status and execute the registered status callback.
|
||||||
|
*/
|
||||||
|
static void event_status(struct wiimote_t* wm, byte* msg) {
|
||||||
|
int led[4] = {0};
|
||||||
|
int attachment = 0;
|
||||||
|
int ir = 0;
|
||||||
|
int exp_changed = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An event occured.
|
||||||
|
* This event can be overwritten by a more specific
|
||||||
|
* event type during a handshake or expansion removal.
|
||||||
|
*/
|
||||||
|
wm->event = WIIUSE_STATUS;
|
||||||
|
|
||||||
|
wiiuse_pressed_buttons(wm, msg);
|
||||||
|
|
||||||
|
/* find what LEDs are lit */
|
||||||
|
if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_1) led[0] = 1;
|
||||||
|
if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_2) led[1] = 1;
|
||||||
|
if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_3) led[2] = 1;
|
||||||
|
if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_4) led[3] = 1;
|
||||||
|
|
||||||
|
/* is an attachment connected to the expansion port? */
|
||||||
|
if ((msg[2] & WM_CTRL_STATUS_BYTE1_ATTACHMENT) == WM_CTRL_STATUS_BYTE1_ATTACHMENT)
|
||||||
|
attachment = 1;
|
||||||
|
|
||||||
|
/* is the speaker enabled? */
|
||||||
|
if ((msg[2] & WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED) == WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED)
|
||||||
|
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_SPEAKER);
|
||||||
|
|
||||||
|
/* is IR sensing enabled? */
|
||||||
|
if ((msg[2] & WM_CTRL_STATUS_BYTE1_IR_ENABLED) == WM_CTRL_STATUS_BYTE1_IR_ENABLED)
|
||||||
|
ir = 1;
|
||||||
|
|
||||||
|
/* find the battery level and normalize between 0 and 1 */
|
||||||
|
wm->battery_level = (msg[5] / (float)WM_MAX_BATTERY_CODE);
|
||||||
|
|
||||||
|
/* expansion port */
|
||||||
|
if (attachment && !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) {
|
||||||
|
/* send the initialization code for the attachment */
|
||||||
|
handshake_expansion(wm, NULL, 0);
|
||||||
|
exp_changed = 1;
|
||||||
|
} else if (!attachment && WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) {
|
||||||
|
/* attachment removed */
|
||||||
|
disable_expansion(wm);
|
||||||
|
exp_changed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
if (!attachment) {
|
||||||
|
WIIUSE_DEBUG("Setting timeout to normal %i ms.", wm->normal_timeout);
|
||||||
|
wm->timeout = wm->normal_timeout;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From now on the remote will only send status packets.
|
||||||
|
* We need to send a WIIMOTE_CMD_REPORT_TYPE packet to
|
||||||
|
* reenable other incoming reports.
|
||||||
|
*/
|
||||||
|
if (exp_changed && WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
|
||||||
|
/*
|
||||||
|
* Since the expansion status changed IR needs to
|
||||||
|
* be reset for the new IR report mode.
|
||||||
|
*/
|
||||||
|
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
|
||||||
|
wiiuse_set_ir(wm, 1);
|
||||||
|
} else
|
||||||
|
wiiuse_set_report_type(wm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle data from the expansion.
|
||||||
|
*
|
||||||
|
* @param wm A pointer to a wiimote_t structure.
|
||||||
|
* @param msg The message specified in the event packet for the expansion.
|
||||||
|
*/
|
||||||
|
static void handle_expansion(struct wiimote_t* wm, byte* msg) {
|
||||||
|
switch (wm->exp.type) {
|
||||||
|
case EXP_NUNCHUK:
|
||||||
|
nunchuk_event(&wm->exp.nunchuk, msg);
|
||||||
|
break;
|
||||||
|
case EXP_CLASSIC:
|
||||||
|
classic_ctrl_event(&wm->exp.classic, msg);
|
||||||
|
break;
|
||||||
|
case EXP_GUITAR_HERO_3:
|
||||||
|
guitar_hero_3_event(&wm->exp.gh3, msg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle the handshake data from the expansion device.
|
||||||
|
*
|
||||||
|
* @param wm A pointer to a wiimote_t structure.
|
||||||
|
* @param data The data read in from the device.
|
||||||
|
* @param len The length of the data block, in bytes.
|
||||||
|
*
|
||||||
|
* Tries to determine what kind of expansion was attached
|
||||||
|
* and invoke the correct handshake function.
|
||||||
|
*
|
||||||
|
* If the data is NULL then this function will try to start
|
||||||
|
* a handshake with the expansion.
|
||||||
|
*/
|
||||||
|
void handshake_expansion(struct wiimote_t* wm, byte* data, unsigned short len) {
|
||||||
|
int id;
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
byte* handshake_buf;
|
||||||
|
byte buf = 0x00;
|
||||||
|
|
||||||
|
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP))
|
||||||
|
disable_expansion(wm);
|
||||||
|
|
||||||
|
/* increase the timeout until the handshake completes */
|
||||||
|
#ifdef WIN32
|
||||||
|
WIIUSE_DEBUG("Setting timeout to expansion %i ms.", wm->exp_timeout);
|
||||||
|
wm->timeout = wm->exp_timeout;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wiiuse_write_data(wm, WM_EXP_MEM_ENABLE, &buf, 1);
|
||||||
|
|
||||||
|
/* get the calibration data */
|
||||||
|
handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
|
||||||
|
wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
|
||||||
|
|
||||||
|
/* tell the wiimote to send expansion data */
|
||||||
|
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_EXP);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
id = BIG_ENDIAN_LONG(*(int*)(data + 220));
|
||||||
|
|
||||||
|
/* call the corresponding handshake function for this expansion */
|
||||||
|
switch (id) {
|
||||||
|
case EXP_ID_CODE_NUNCHUK:
|
||||||
|
{
|
||||||
|
if (nunchuk_handshake(wm, &wm->exp.nunchuk, data, len))
|
||||||
|
wm->event = WIIUSE_NUNCHUK_INSERTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EXP_ID_CODE_CLASSIC_CONTROLLER:
|
||||||
|
{
|
||||||
|
if (classic_ctrl_handshake(wm, &wm->exp.classic, data, len))
|
||||||
|
wm->event = WIIUSE_CLASSIC_CTRL_INSERTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EXP_ID_CODE_GUITAR:
|
||||||
|
{
|
||||||
|
if (guitar_hero_3_handshake(wm, &wm->exp.gh3, data, len))
|
||||||
|
wm->event = WIIUSE_GUITAR_HERO_3_CTRL_INSERTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
WIIUSE_WARNING("Unknown expansion type. Code: 0x%x", id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disable the expansion device if it was enabled.
|
||||||
|
*
|
||||||
|
* @param wm A pointer to a wiimote_t structure.
|
||||||
|
* @param data The data read in from the device.
|
||||||
|
* @param len The length of the data block, in bytes.
|
||||||
|
*
|
||||||
|
* If the data is NULL then this function will try to start
|
||||||
|
* a handshake with the expansion.
|
||||||
|
*/
|
||||||
|
void disable_expansion(struct wiimote_t* wm) {
|
||||||
|
if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* tell the assoicated module the expansion was removed */
|
||||||
|
switch (wm->exp.type) {
|
||||||
|
case EXP_NUNCHUK:
|
||||||
|
nunchuk_disconnected(&wm->exp.nunchuk);
|
||||||
|
wm->event = WIIUSE_NUNCHUK_REMOVED;
|
||||||
|
break;
|
||||||
|
case EXP_CLASSIC:
|
||||||
|
classic_ctrl_disconnected(&wm->exp.classic);
|
||||||
|
wm->event = WIIUSE_CLASSIC_CTRL_REMOVED;
|
||||||
|
break;
|
||||||
|
case EXP_GUITAR_HERO_3:
|
||||||
|
guitar_hero_3_disconnected(&wm->exp.gh3);
|
||||||
|
wm->event = WIIUSE_GUITAR_HERO_3_CTRL_REMOVED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
|
||||||
|
wm->exp.type = EXP_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Save important state data.
|
||||||
|
* @param wm A pointer to a wiimote_t structure.
|
||||||
|
*/
|
||||||
|
static void save_state(struct wiimote_t* wm) {
|
||||||
|
/* wiimote */
|
||||||
|
wm->lstate.btns = wm->btns;
|
||||||
|
wm->lstate.accel = wm->accel;
|
||||||
|
|
||||||
|
/* ir */
|
||||||
|
if (WIIUSE_USING_IR(wm)) {
|
||||||
|
wm->lstate.ir_ax = wm->ir.ax;
|
||||||
|
wm->lstate.ir_ay = wm->ir.ay;
|
||||||
|
wm->lstate.ir_distance = wm->ir.distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* expansion */
|
||||||
|
switch (wm->exp.type) {
|
||||||
|
case EXP_NUNCHUK:
|
||||||
|
wm->lstate.exp_ljs_ang = wm->exp.nunchuk.js.ang;
|
||||||
|
wm->lstate.exp_ljs_mag = wm->exp.nunchuk.js.mag;
|
||||||
|
wm->lstate.exp_btns = wm->exp.nunchuk.btns;
|
||||||
|
wm->lstate.exp_accel = wm->exp.nunchuk.accel;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXP_CLASSIC:
|
||||||
|
wm->lstate.exp_ljs_ang = wm->exp.classic.ljs.ang;
|
||||||
|
wm->lstate.exp_ljs_mag = wm->exp.classic.ljs.mag;
|
||||||
|
wm->lstate.exp_rjs_ang = wm->exp.classic.rjs.ang;
|
||||||
|
wm->lstate.exp_rjs_mag = wm->exp.classic.rjs.mag;
|
||||||
|
wm->lstate.exp_r_shoulder = wm->exp.classic.r_shoulder;
|
||||||
|
wm->lstate.exp_l_shoulder = wm->exp.classic.l_shoulder;
|
||||||
|
wm->lstate.exp_btns = wm->exp.classic.btns;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXP_GUITAR_HERO_3:
|
||||||
|
wm->lstate.exp_ljs_ang = wm->exp.gh3.js.ang;
|
||||||
|
wm->lstate.exp_ljs_mag = wm->exp.gh3.js.mag;
|
||||||
|
wm->lstate.exp_r_shoulder = wm->exp.gh3.whammy_bar;
|
||||||
|
wm->lstate.exp_btns = wm->exp.gh3.btns;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXP_NONE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Determine if the current state differs significantly from the previous.
|
||||||
|
* @param wm A pointer to a wiimote_t structure.
|
||||||
|
* @return 1 if a significant change occured, 0 if not.
|
||||||
|
*/
|
||||||
|
static int state_changed(struct wiimote_t* wm) {
|
||||||
|
#define STATE_CHANGED(a, b) if (a != b) return 1
|
||||||
|
|
||||||
|
#define CROSS_THRESH(last, now, thresh) \
|
||||||
|
do { \
|
||||||
|
if (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_ORIENT_THRESH)) { \
|
||||||
|
if ((diff_f(last.roll, now.roll) >= thresh) || \
|
||||||
|
(diff_f(last.pitch, now.pitch) >= thresh) || \
|
||||||
|
(diff_f(last.yaw, now.yaw) >= thresh)) \
|
||||||
|
{ \
|
||||||
|
last = now; \
|
||||||
|
return 1; \
|
||||||
|
} \
|
||||||
|
} else { \
|
||||||
|
if (last.roll != now.roll) return 1; \
|
||||||
|
if (last.pitch != now.pitch) return 1; \
|
||||||
|
if (last.yaw != now.yaw) return 1; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define CROSS_THRESH_XYZ(last, now, thresh) \
|
||||||
|
do { \
|
||||||
|
if (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_ORIENT_THRESH)) { \
|
||||||
|
if ((diff_f(last.x, now.x) >= thresh) || \
|
||||||
|
(diff_f(last.y, now.y) >= thresh) || \
|
||||||
|
(diff_f(last.z, now.z) >= thresh)) \
|
||||||
|
{ \
|
||||||
|
last = now; \
|
||||||
|
return 1; \
|
||||||
|
} \
|
||||||
|
} else { \
|
||||||
|
if (last.x != now.x) return 1; \
|
||||||
|
if (last.y != now.y) return 1; \
|
||||||
|
if (last.z != now.z) return 1; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* ir */
|
||||||
|
if (WIIUSE_USING_IR(wm)) {
|
||||||
|
STATE_CHANGED(wm->lstate.ir_ax, wm->ir.ax);
|
||||||
|
STATE_CHANGED(wm->lstate.ir_ay, wm->ir.ay);
|
||||||
|
STATE_CHANGED(wm->lstate.ir_distance, wm->ir.distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* accelerometer */
|
||||||
|
if (WIIUSE_USING_ACC(wm)) {
|
||||||
|
/* raw accelerometer */
|
||||||
|
CROSS_THRESH_XYZ(wm->lstate.accel, wm->accel, wm->accel_threshold);
|
||||||
|
|
||||||
|
/* orientation */
|
||||||
|
CROSS_THRESH(wm->lstate.orient, wm->orient, wm->orient_threshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* expansion */
|
||||||
|
switch (wm->exp.type) {
|
||||||
|
case EXP_NUNCHUK:
|
||||||
|
{
|
||||||
|
STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.nunchuk.js.ang);
|
||||||
|
STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.nunchuk.js.mag);
|
||||||
|
STATE_CHANGED(wm->lstate.exp_btns, wm->exp.nunchuk.btns);
|
||||||
|
|
||||||
|
CROSS_THRESH(wm->lstate.exp_orient, wm->exp.nunchuk.orient, wm->exp.nunchuk.orient_threshold);
|
||||||
|
CROSS_THRESH_XYZ(wm->lstate.exp_accel, wm->exp.nunchuk.accel, wm->exp.nunchuk.accel_threshold);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EXP_CLASSIC:
|
||||||
|
{
|
||||||
|
STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.classic.ljs.ang);
|
||||||
|
STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.classic.ljs.mag);
|
||||||
|
STATE_CHANGED(wm->lstate.exp_rjs_ang, wm->exp.classic.rjs.ang);
|
||||||
|
STATE_CHANGED(wm->lstate.exp_rjs_mag, wm->exp.classic.rjs.mag);
|
||||||
|
STATE_CHANGED(wm->lstate.exp_r_shoulder, wm->exp.classic.r_shoulder);
|
||||||
|
STATE_CHANGED(wm->lstate.exp_l_shoulder, wm->exp.classic.l_shoulder);
|
||||||
|
STATE_CHANGED(wm->lstate.exp_btns, wm->exp.classic.btns);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EXP_GUITAR_HERO_3:
|
||||||
|
{
|
||||||
|
STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.gh3.js.ang);
|
||||||
|
STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.gh3.js.mag);
|
||||||
|
STATE_CHANGED(wm->lstate.exp_r_shoulder, wm->exp.gh3.whammy_bar);
|
||||||
|
STATE_CHANGED(wm->lstate.exp_btns, wm->exp.gh3.btns);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EXP_NONE:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STATE_CHANGED(wm->lstate.btns, wm->btns);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
54
src/events.h
Normal file
54
src/events.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Handles wiimote events.
|
||||||
|
*
|
||||||
|
* The file includes functions that handle the events
|
||||||
|
* that are sent from the wiimote to us.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EVENTS_H_INCLUDED
|
||||||
|
#define EVENTS_H_INCLUDED
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void wiiuse_pressed_buttons(struct wiimote_t* wm, byte* msg);
|
||||||
|
|
||||||
|
void handshake_expansion(struct wiimote_t* wm, byte* data, unsigned short len);
|
||||||
|
void disable_expansion(struct wiimote_t* wm);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif // EVENTS_H_INCLUDED
|
||||||
172
src/guitar_hero_3.c
Normal file
172
src/guitar_hero_3.c
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Guitar Hero 3 expansion device.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <Winsock2.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "definitions.h"
|
||||||
|
#include "wiiuse_internal.h"
|
||||||
|
#include "dynamics.h"
|
||||||
|
#include "events.h"
|
||||||
|
#include "guitar_hero_3.h"
|
||||||
|
|
||||||
|
static void guitar_hero_3_pressed_buttons(struct guitar_hero_3_t* gh3, short now);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle the handshake data from the guitar.
|
||||||
|
*
|
||||||
|
* @param cc A pointer to a classic_ctrl_t structure.
|
||||||
|
* @param data The data read in from the device.
|
||||||
|
* @param len The length of the data block, in bytes.
|
||||||
|
*
|
||||||
|
* @return Returns 1 if handshake was successful, 0 if not.
|
||||||
|
*/
|
||||||
|
int guitar_hero_3_handshake(struct wiimote_t* wm, struct guitar_hero_3_t* gh3, byte* data, unsigned short len) {
|
||||||
|
int i;
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The good fellows that made the Guitar Hero 3 controller
|
||||||
|
* failed to factory calibrate the devices. There is no
|
||||||
|
* calibration data on the device.
|
||||||
|
*/
|
||||||
|
|
||||||
|
gh3->btns = 0;
|
||||||
|
gh3->btns_held = 0;
|
||||||
|
gh3->btns_released = 0;
|
||||||
|
gh3->whammy_bar = 0.0f;
|
||||||
|
|
||||||
|
/* decrypt data */
|
||||||
|
for (i = 0; i < len; ++i)
|
||||||
|
data[i] = (data[i] ^ 0x17) + 0x17;
|
||||||
|
|
||||||
|
if (data[offset] == 0xFF) {
|
||||||
|
/*
|
||||||
|
* Sometimes the data returned here is not correct.
|
||||||
|
* This might happen because the wiimote is lagging
|
||||||
|
* behind our initialization sequence.
|
||||||
|
* To fix this just request the handshake again.
|
||||||
|
*
|
||||||
|
* Other times it's just the first 16 bytes are 0xFF,
|
||||||
|
* but since the next 16 bytes are the same, just use
|
||||||
|
* those.
|
||||||
|
*/
|
||||||
|
if (data[offset + 16] == 0xFF) {
|
||||||
|
/* get the calibration data */
|
||||||
|
byte* handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
|
||||||
|
|
||||||
|
WIIUSE_DEBUG("Guitar Hero 3 handshake appears invalid, trying again.");
|
||||||
|
wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
offset += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* joystick stuff */
|
||||||
|
gh3->js.max.x = GUITAR_HERO_3_JS_MAX_X;
|
||||||
|
gh3->js.min.x = GUITAR_HERO_3_JS_MIN_X;
|
||||||
|
gh3->js.center.x = GUITAR_HERO_3_JS_CENTER_X;
|
||||||
|
gh3->js.max.y = GUITAR_HERO_3_JS_MAX_Y;
|
||||||
|
gh3->js.min.y = GUITAR_HERO_3_JS_MIN_Y;
|
||||||
|
gh3->js.center.y = GUITAR_HERO_3_JS_CENTER_Y;
|
||||||
|
|
||||||
|
/* handshake done */
|
||||||
|
wm->exp.type = EXP_GUITAR_HERO_3;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The guitar disconnected.
|
||||||
|
*
|
||||||
|
* @param cc A pointer to a classic_ctrl_t structure.
|
||||||
|
*/
|
||||||
|
void guitar_hero_3_disconnected(struct guitar_hero_3_t* gh3) {
|
||||||
|
memset(gh3, 0, sizeof(struct guitar_hero_3_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle guitar event.
|
||||||
|
*
|
||||||
|
* @param cc A pointer to a classic_ctrl_t structure.
|
||||||
|
* @param msg The message specified in the event packet.
|
||||||
|
*/
|
||||||
|
void guitar_hero_3_event(struct guitar_hero_3_t* gh3, byte* msg) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* decrypt data */
|
||||||
|
for (i = 0; i < 6; ++i)
|
||||||
|
msg[i] = (msg[i] ^ 0x17) + 0x17;
|
||||||
|
|
||||||
|
guitar_hero_3_pressed_buttons(gh3, BIG_ENDIAN_SHORT(*(short*)(msg + 4)));
|
||||||
|
|
||||||
|
/* whammy bar */
|
||||||
|
gh3->whammy_bar = (msg[3] - GUITAR_HERO_3_WHAMMY_BAR_MIN) / (float)(GUITAR_HERO_3_WHAMMY_BAR_MAX - GUITAR_HERO_3_WHAMMY_BAR_MIN);
|
||||||
|
|
||||||
|
/* joy stick */
|
||||||
|
calc_joystick_state(&gh3->js, msg[0], msg[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Find what buttons are pressed.
|
||||||
|
*
|
||||||
|
* @param cc A pointer to a classic_ctrl_t structure.
|
||||||
|
* @param msg The message byte specified in the event packet.
|
||||||
|
*/
|
||||||
|
static void guitar_hero_3_pressed_buttons(struct guitar_hero_3_t* gh3, short now) {
|
||||||
|
/* message is inverted (0 is active, 1 is inactive) */
|
||||||
|
now = ~now & GUITAR_HERO_3_BUTTON_ALL;
|
||||||
|
|
||||||
|
/* pressed now & were pressed, then held */
|
||||||
|
gh3->btns_held = (now & gh3->btns);
|
||||||
|
|
||||||
|
/* were pressed or were held & not pressed now, then released */
|
||||||
|
gh3->btns_released = ((gh3->btns | gh3->btns_held) & ~now);
|
||||||
|
|
||||||
|
/* buttons pressed now */
|
||||||
|
gh3->btns = now;
|
||||||
|
}
|
||||||
62
src/guitar_hero_3.h
Normal file
62
src/guitar_hero_3.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Guitar Hero 3 expansion device.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GUITAR_HERO_3_H_INCLUDED
|
||||||
|
#define GUITAR_HERO_3_H_INCLUDED
|
||||||
|
|
||||||
|
#include "wiiuse_internal.h"
|
||||||
|
|
||||||
|
#define GUITAR_HERO_3_JS_MIN_X 0xC5
|
||||||
|
#define GUITAR_HERO_3_JS_MAX_X 0xFC
|
||||||
|
#define GUITAR_HERO_3_JS_CENTER_X 0xE0
|
||||||
|
#define GUITAR_HERO_3_JS_MIN_Y 0xC5
|
||||||
|
#define GUITAR_HERO_3_JS_MAX_Y 0xFA
|
||||||
|
#define GUITAR_HERO_3_JS_CENTER_Y 0xE0
|
||||||
|
#define GUITAR_HERO_3_WHAMMY_BAR_MIN 0xEF
|
||||||
|
#define GUITAR_HERO_3_WHAMMY_BAR_MAX 0xFA
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int guitar_hero_3_handshake(struct wiimote_t* wm, struct guitar_hero_3_t* gh3, byte* data, unsigned short len);
|
||||||
|
|
||||||
|
void guitar_hero_3_disconnected(struct guitar_hero_3_t* gh3);
|
||||||
|
|
||||||
|
void guitar_hero_3_event(struct guitar_hero_3_t* gh3, byte* msg);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // GUITAR_HERO_3_H_INCLUDED
|
||||||
119
src/io.c
Normal file
119
src/io.c
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Handles device I/O (non-OS specific).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "definitions.h"
|
||||||
|
#include "wiiuse_internal.h"
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get initialization data from the wiimote.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param data unused
|
||||||
|
* @param len unused
|
||||||
|
*
|
||||||
|
* When first called for a wiimote_t structure, a request
|
||||||
|
* is sent to the wiimote for initialization information.
|
||||||
|
* This includes factory set accelerometer data.
|
||||||
|
* The handshake will be concluded when the wiimote responds
|
||||||
|
* with this data.
|
||||||
|
*/
|
||||||
|
void wiiuse_handshake(struct wiimote_t* wm, byte* data, unsigned short len) {
|
||||||
|
if (!wm) return;
|
||||||
|
|
||||||
|
switch (wm->handshake_state) {
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
/* send request to wiimote for accelerometer calibration */
|
||||||
|
byte* buf;
|
||||||
|
|
||||||
|
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
|
||||||
|
wiiuse_set_leds(wm, WIIMOTE_LED_NONE);
|
||||||
|
|
||||||
|
buf = (byte*)malloc(sizeof(byte) * 8);
|
||||||
|
wiiuse_read_data_cb(wm, wiiuse_handshake, buf, WM_MEM_OFFSET_CALIBRATION, 7);
|
||||||
|
wm->handshake_state++;
|
||||||
|
|
||||||
|
wiiuse_set_leds(wm, WIIMOTE_LED_NONE);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
struct read_req_t* req = wm->read_req;
|
||||||
|
struct accel_t* accel = &wm->accel_calib;
|
||||||
|
|
||||||
|
/* received read data */
|
||||||
|
accel->cal_zero.x = req->buf[0];
|
||||||
|
accel->cal_zero.y = req->buf[1];
|
||||||
|
accel->cal_zero.z = req->buf[2];
|
||||||
|
|
||||||
|
accel->cal_g.x = req->buf[4] - accel->cal_zero.x;
|
||||||
|
accel->cal_g.y = req->buf[5] - accel->cal_zero.y;
|
||||||
|
accel->cal_g.z = req->buf[6] - accel->cal_zero.z;
|
||||||
|
|
||||||
|
/* done with the buffer */
|
||||||
|
free(req->buf);
|
||||||
|
|
||||||
|
/* handshake is done */
|
||||||
|
WIIUSE_DEBUG("Handshake finished. Calibration: Idle: X=%x Y=%x Z=%x\t+1g: X=%x Y=%x Z=%x",
|
||||||
|
accel->cal_zero.x, accel->cal_zero.y, accel->cal_zero.z,
|
||||||
|
accel->cal_g.x, accel->cal_g.y, accel->cal_g.z);
|
||||||
|
|
||||||
|
|
||||||
|
/* request the status of the wiimote to see if there is an expansion */
|
||||||
|
wiiuse_status(wm);
|
||||||
|
|
||||||
|
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
|
||||||
|
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE);
|
||||||
|
wm->handshake_state++;
|
||||||
|
|
||||||
|
/* now enable IR if it was set before the handshake completed */
|
||||||
|
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
|
||||||
|
WIIUSE_DEBUG("Handshake finished, enabling IR.");
|
||||||
|
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
|
||||||
|
wiiuse_set_ir(wm, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
56
src/io.h
Normal file
56
src/io.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Handles device I/O.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONNECT_H_INCLUDED
|
||||||
|
#define CONNECT_H_INCLUDED
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <bluetooth/bluetooth.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "wiiuse_internal.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void wiiuse_handshake(struct wiimote_t* wm, byte* data, unsigned short len);
|
||||||
|
|
||||||
|
int wiiuse_io_read(struct wiimote_t* wm);
|
||||||
|
int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // CONNECT_H_INCLUDED
|
||||||
270
src/io_nix.c
Normal file
270
src/io_nix.c
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Handles device I/O for *nix.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <bluetooth/bluetooth.h>
|
||||||
|
#include <bluetooth/hci.h>
|
||||||
|
#include <bluetooth/hci_lib.h>
|
||||||
|
#include <bluetooth/l2cap.h>
|
||||||
|
|
||||||
|
#include "definitions.h"
|
||||||
|
#include "wiiuse_internal.h"
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
static int wiiuse_connect_single(struct wiimote_t* wm, char* address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Find a wiimote or wiimotes.
|
||||||
|
*
|
||||||
|
* @param wm An array of wiimote_t structures.
|
||||||
|
* @param max_wiimotes The number of wiimote structures in \a wm.
|
||||||
|
* @param timeout The number of seconds before the search times out.
|
||||||
|
*
|
||||||
|
* @return The number of wiimotes found.
|
||||||
|
*
|
||||||
|
* @see wiimote_connect()
|
||||||
|
*
|
||||||
|
* This function will only look for wiimote devices. \n
|
||||||
|
* When a device is found the address in the structures will be set. \n
|
||||||
|
* You can then call wiimote_connect() to connect to the found \n
|
||||||
|
* devices.
|
||||||
|
*/
|
||||||
|
int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) {
|
||||||
|
int device_id;
|
||||||
|
int device_sock;
|
||||||
|
int found_devices;
|
||||||
|
int found_wiimotes;
|
||||||
|
|
||||||
|
/* reset all wiimote bluetooth device addresses */
|
||||||
|
for (found_wiimotes = 0; found_wiimotes < max_wiimotes; ++found_wiimotes)
|
||||||
|
wm[found_wiimotes]->bdaddr = *BDADDR_ANY;
|
||||||
|
found_wiimotes = 0;
|
||||||
|
|
||||||
|
/* get the id of the first bluetooth device. */
|
||||||
|
device_id = hci_get_route(NULL);
|
||||||
|
if (device_id < 0) {
|
||||||
|
perror("hci_get_route");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create a socket to the device */
|
||||||
|
device_sock = hci_open_dev(device_id);
|
||||||
|
if (device_sock < 0) {
|
||||||
|
perror("hci_open_dev");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inquiry_info scan_info_arr[128];
|
||||||
|
inquiry_info* scan_info = scan_info_arr;
|
||||||
|
memset(&scan_info_arr, 0, sizeof(scan_info_arr));
|
||||||
|
|
||||||
|
/* scan for bluetooth devices for 'timeout' seconds */
|
||||||
|
found_devices = hci_inquiry(device_id, timeout, 128, NULL, &scan_info, IREQ_CACHE_FLUSH);
|
||||||
|
if (found_devices < 0) {
|
||||||
|
perror("hci_inquiry");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WIIUSE_INFO("Found %i bluetooth device(s).", found_devices);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
/* display discovered devices */
|
||||||
|
for (; (i < found_devices) && (found_wiimotes < max_wiimotes); ++i) {
|
||||||
|
if ((scan_info[i].dev_class[0] == WM_DEV_CLASS_0) &&
|
||||||
|
(scan_info[i].dev_class[1] == WM_DEV_CLASS_1) &&
|
||||||
|
(scan_info[i].dev_class[2] == WM_DEV_CLASS_2))
|
||||||
|
{
|
||||||
|
/* found a device */
|
||||||
|
ba2str(&scan_info[i].bdaddr, wm[found_wiimotes]->bdaddr_str);
|
||||||
|
|
||||||
|
WIIUSE_INFO("Found wiimote (%s) [id %i].", wm[found_wiimotes]->bdaddr_str, wm[found_wiimotes]->unid);
|
||||||
|
|
||||||
|
wm[found_wiimotes]->bdaddr = scan_info[i].bdaddr;
|
||||||
|
WIIMOTE_ENABLE_STATE(wm[found_wiimotes], WIIMOTE_STATE_DEV_FOUND);
|
||||||
|
++found_wiimotes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(device_sock);
|
||||||
|
return found_wiimotes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Connect to a wiimote or wiimotes once an address is known.
|
||||||
|
*
|
||||||
|
* @param wm An array of wiimote_t structures.
|
||||||
|
* @param wiimotes The number of wiimote structures in \a wm.
|
||||||
|
*
|
||||||
|
* @return The number of wiimotes that successfully connected.
|
||||||
|
*
|
||||||
|
* @see wiiuse_find()
|
||||||
|
* @see wiiuse_connect_single()
|
||||||
|
* @see wiiuse_disconnect()
|
||||||
|
*
|
||||||
|
* Connect to a number of wiimotes when the address is already set
|
||||||
|
* in the wiimote_t structures. These addresses are normally set
|
||||||
|
* by the wiiuse_find() function, but can also be set manually.
|
||||||
|
*/
|
||||||
|
int wiiuse_connect(struct wiimote_t** wm, int wiimotes) {
|
||||||
|
int connected = 0;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (; i < wiimotes; ++i) {
|
||||||
|
if (!WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_DEV_FOUND))
|
||||||
|
/* if the device address is not set, skip it */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (wiiuse_connect_single(wm[i], NULL))
|
||||||
|
++connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
return connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Connect to a wiimote with a known address.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param address The address of the device to connect to.
|
||||||
|
* If NULL, use the address in the struct set by wiiuse_find().
|
||||||
|
*
|
||||||
|
* @return 1 on success, 0 on failure
|
||||||
|
*/
|
||||||
|
static int wiiuse_connect_single(struct wiimote_t* wm, char* address) {
|
||||||
|
struct sockaddr_l2 addr;
|
||||||
|
|
||||||
|
if (!wm || WIIMOTE_IS_CONNECTED(wm))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
addr.l2_family = AF_BLUETOOTH;
|
||||||
|
|
||||||
|
if (address)
|
||||||
|
/* use provided address */
|
||||||
|
str2ba(address, &addr.l2_bdaddr);
|
||||||
|
else
|
||||||
|
/* use address of device discovered */
|
||||||
|
addr.l2_bdaddr = wm->bdaddr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OUTPUT CHANNEL
|
||||||
|
*/
|
||||||
|
wm->out_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
|
||||||
|
if (wm->out_sock == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
addr.l2_psm = htobs(WM_OUTPUT_CHANNEL);
|
||||||
|
|
||||||
|
/* connect to wiimote */
|
||||||
|
if (connect(wm->out_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
|
||||||
|
perror("connect() output sock");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* INPUT CHANNEL
|
||||||
|
*/
|
||||||
|
wm->in_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
|
||||||
|
if (wm->in_sock == -1) {
|
||||||
|
close(wm->out_sock);
|
||||||
|
wm->out_sock = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr.l2_psm = htobs(WM_INPUT_CHANNEL);
|
||||||
|
|
||||||
|
/* connect to wiimote */
|
||||||
|
if (connect(wm->in_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
|
||||||
|
perror("connect() interrupt sock");
|
||||||
|
close(wm->out_sock);
|
||||||
|
wm->out_sock = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WIIUSE_INFO("Connected to wiimote [id %i].", wm->unid);
|
||||||
|
|
||||||
|
/* do the handshake */
|
||||||
|
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
|
||||||
|
wiiuse_handshake(wm, NULL, 0);
|
||||||
|
|
||||||
|
wiiuse_set_report_type(wm);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disconnect a wiimote.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
*
|
||||||
|
* @see wiiuse_connect()
|
||||||
|
*
|
||||||
|
* Note that this will not free the wiimote structure.
|
||||||
|
*/
|
||||||
|
void wiiuse_disconnect(struct wiimote_t* wm) {
|
||||||
|
if (!wm || WIIMOTE_IS_CONNECTED(wm))
|
||||||
|
return;
|
||||||
|
|
||||||
|
close(wm->out_sock);
|
||||||
|
close(wm->in_sock);
|
||||||
|
|
||||||
|
wm->out_sock = -1;
|
||||||
|
wm->in_sock = -1;
|
||||||
|
wm->event = WIIUSE_NONE;
|
||||||
|
|
||||||
|
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
|
||||||
|
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wiiuse_io_read(struct wiimote_t* wm) {
|
||||||
|
/* not used */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len) {
|
||||||
|
return write(wm->out_sock, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ifndef WIN32 */
|
||||||
247
src/io_win.c
Normal file
247
src/io_win.c
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Handles device I/O for Windows.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <hidsdi.h>
|
||||||
|
#include <setupapi.h>
|
||||||
|
|
||||||
|
#include "definitions.h"
|
||||||
|
#include "wiiuse_internal.h"
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
|
||||||
|
int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) {
|
||||||
|
GUID device_id;
|
||||||
|
HANDLE dev;
|
||||||
|
HDEVINFO device_info;
|
||||||
|
int i, index;
|
||||||
|
DWORD len;
|
||||||
|
SP_DEVICE_INTERFACE_DATA device_data;
|
||||||
|
PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL;
|
||||||
|
HIDD_ATTRIBUTES attr;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
(void) timeout; // unused
|
||||||
|
|
||||||
|
device_data.cbSize = sizeof(device_data);
|
||||||
|
index = 0;
|
||||||
|
|
||||||
|
/* get the device id */
|
||||||
|
HidD_GetHidGuid(&device_id);
|
||||||
|
|
||||||
|
/* get all hid devices connected */
|
||||||
|
device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
|
||||||
|
|
||||||
|
for (;; ++index) {
|
||||||
|
|
||||||
|
if (detail_data) {
|
||||||
|
free(detail_data);
|
||||||
|
detail_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* query the next hid device info */
|
||||||
|
if (!SetupDiEnumDeviceInterfaces(device_info, NULL, &device_id, index, &device_data))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* get the size of the data block required */
|
||||||
|
i = SetupDiGetDeviceInterfaceDetail(device_info, &device_data, NULL, 0, &len, NULL);
|
||||||
|
detail_data = malloc(len);
|
||||||
|
detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
|
||||||
|
|
||||||
|
/* query the data for this device */
|
||||||
|
if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* open the device */
|
||||||
|
dev = CreateFile(detail_data->DevicePath,
|
||||||
|
(GENERIC_READ | GENERIC_WRITE),
|
||||||
|
(FILE_SHARE_READ | FILE_SHARE_WRITE),
|
||||||
|
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
||||||
|
if (dev == INVALID_HANDLE_VALUE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* get device attributes */
|
||||||
|
attr.Size = sizeof(attr);
|
||||||
|
i = HidD_GetAttributes(dev, &attr);
|
||||||
|
|
||||||
|
if ((attr.VendorID == WM_VENDOR_ID) && (attr.ProductID == WM_PRODUCT_ID)) {
|
||||||
|
/* this is a wiimote */
|
||||||
|
wm[found]->dev_handle = dev;
|
||||||
|
|
||||||
|
wm[found]->hid_overlap.hEvent = CreateEvent(NULL, 1, 1, "");
|
||||||
|
wm[found]->hid_overlap.Offset = 0;
|
||||||
|
wm[found]->hid_overlap.OffsetHigh = 0;
|
||||||
|
|
||||||
|
WIIMOTE_ENABLE_STATE(wm[found], WIIMOTE_STATE_DEV_FOUND);
|
||||||
|
WIIMOTE_ENABLE_STATE(wm[found], WIIMOTE_STATE_CONNECTED);
|
||||||
|
|
||||||
|
/* try to set the output report to see if the device is actually connected */
|
||||||
|
if (!wiiuse_set_report_type(wm[found])) {
|
||||||
|
WIIMOTE_DISABLE_STATE(wm[found], WIIMOTE_STATE_CONNECTED);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do the handshake */
|
||||||
|
wiiuse_handshake(wm[found], NULL, 0);
|
||||||
|
|
||||||
|
WIIUSE_INFO("Connected to wiimote [id %i].", wm[found]->unid);
|
||||||
|
|
||||||
|
++found;
|
||||||
|
if (found >= max_wiimotes)
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
/* not a wiimote */
|
||||||
|
CloseHandle(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (detail_data)
|
||||||
|
free(detail_data);
|
||||||
|
|
||||||
|
SetupDiDestroyDeviceInfoList(device_info);
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wiiuse_connect(struct wiimote_t** wm, int wiimotes) {
|
||||||
|
int connected = 0;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (; i < wiimotes; ++i) {
|
||||||
|
if (WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_CONNECTED))
|
||||||
|
++connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
return connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wiiuse_disconnect(struct wiimote_t* wm) {
|
||||||
|
if (!wm || WIIMOTE_IS_CONNECTED(wm))
|
||||||
|
return;
|
||||||
|
|
||||||
|
CloseHandle(wm->dev_handle);
|
||||||
|
wm->dev_handle = 0;
|
||||||
|
|
||||||
|
ResetEvent(&wm->hid_overlap);
|
||||||
|
|
||||||
|
wm->event = WIIUSE_NONE;
|
||||||
|
|
||||||
|
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
|
||||||
|
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wiiuse_io_read(struct wiimote_t* wm) {
|
||||||
|
DWORD b, r;
|
||||||
|
|
||||||
|
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!ReadFile(wm->dev_handle, wm->event_buf, sizeof(wm->event_buf), &b, &wm->hid_overlap)) {
|
||||||
|
/* partial read */
|
||||||
|
b = GetLastError();
|
||||||
|
|
||||||
|
if ((b == ERROR_HANDLE_EOF) || (b == ERROR_DEVICE_NOT_CONNECTED)) {
|
||||||
|
/* remote disconnect */
|
||||||
|
wiiuse_disconnected(wm);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = WaitForSingleObject(wm->hid_overlap.hEvent, wm->timeout);
|
||||||
|
if (r == WAIT_TIMEOUT) {
|
||||||
|
/* timeout - cancel and continue */
|
||||||
|
|
||||||
|
if (*wm->event_buf)
|
||||||
|
WIIUSE_WARNING("Packet ignored. This may indicate a problem (timeout is %i ms).", wm->timeout);
|
||||||
|
|
||||||
|
CancelIo(wm->dev_handle);
|
||||||
|
ResetEvent(wm->hid_overlap.hEvent);
|
||||||
|
return 0;
|
||||||
|
} else if (r == WAIT_FAILED) {
|
||||||
|
WIIUSE_WARNING("A wait error occured on reading from wiimote %i.", wm->unid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetOverlappedResult(wm->dev_handle, &wm->hid_overlap, &b, 0))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetEvent(wm->hid_overlap.hEvent);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len) {
|
||||||
|
DWORD bytes;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (wm->stack) {
|
||||||
|
case WIIUSE_STACK_UNKNOWN:
|
||||||
|
{
|
||||||
|
/* try to auto-detect the stack type */
|
||||||
|
if (i = WriteFile(wm->dev_handle, buf, 22, &bytes, &wm->hid_overlap)) {
|
||||||
|
/* bluesoleil will always return 1 here, even if it's not connected */
|
||||||
|
wm->stack = WIIUSE_STACK_BLUESOLEIL;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i = HidD_SetOutputReport(wm->dev_handle, buf, len)) {
|
||||||
|
wm->stack = WIIUSE_STACK_MS;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
WIIUSE_ERROR("Unable to determine bluetooth stack type.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WIIUSE_STACK_MS:
|
||||||
|
return HidD_SetOutputReport(wm->dev_handle, buf, len);
|
||||||
|
|
||||||
|
case WIIUSE_STACK_BLUESOLEIL:
|
||||||
|
return WriteFile(wm->dev_handle, buf, 22, &bytes, &wm->hid_overlap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ifdef WIN32 */
|
||||||
748
src/ir.c
Normal file
748
src/ir.c
Normal file
@@ -0,0 +1,748 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Handles IR data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "definitions.h"
|
||||||
|
#include "wiiuse_internal.h"
|
||||||
|
#include "ir.h"
|
||||||
|
|
||||||
|
static int get_ir_sens(struct wiimote_t* wm, char** block1, char** block2);
|
||||||
|
static void interpret_ir_data(struct wiimote_t* wm);
|
||||||
|
static void fix_rotated_ir_dots(struct ir_dot_t* dot, float ang);
|
||||||
|
static void get_ir_dot_avg(struct ir_dot_t* dot, int* x, int* y);
|
||||||
|
static void reorder_ir_dots(struct ir_dot_t* dot);
|
||||||
|
static float ir_distance(struct ir_dot_t* dot);
|
||||||
|
static int ir_correct_for_bounds(int* x, int* y, enum aspect_t aspect, int offset_x, int offset_y);
|
||||||
|
static void ir_convert_to_vres(int* x, int* y, enum aspect_t aspect, int vx, int vy);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set if the wiimote should track IR targets.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param status 1 to enable, 0 to disable.
|
||||||
|
*/
|
||||||
|
void wiiuse_set_ir(struct wiimote_t* wm, int status) {
|
||||||
|
byte buf;
|
||||||
|
char* block1 = NULL;
|
||||||
|
char* block2 = NULL;
|
||||||
|
int ir_level;
|
||||||
|
|
||||||
|
if (!wm)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for the handshake to finish first.
|
||||||
|
* When it handshake finishes and sees that
|
||||||
|
* IR is enabled, it will call this function
|
||||||
|
* again to actually enable IR.
|
||||||
|
*/
|
||||||
|
if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE)) {
|
||||||
|
WIIUSE_DEBUG("Tried to enable IR, will wait until handshake finishes.");
|
||||||
|
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to make sure a sensitivity setting is selected.
|
||||||
|
*/
|
||||||
|
ir_level = get_ir_sens(wm, &block1, &block2);
|
||||||
|
if (!ir_level) {
|
||||||
|
WIIUSE_ERROR("No IR sensitivity setting selected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
/* if already enabled then stop */
|
||||||
|
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR))
|
||||||
|
return;
|
||||||
|
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR);
|
||||||
|
} else {
|
||||||
|
/* if already disabled then stop */
|
||||||
|
if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR))
|
||||||
|
return;
|
||||||
|
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set camera 1 and 2 */
|
||||||
|
buf = (status ? 0x04 : 0x00);
|
||||||
|
wiiuse_send(wm, WM_CMD_IR, &buf, 1);
|
||||||
|
wiiuse_send(wm, WM_CMD_IR_2, &buf, 1);
|
||||||
|
|
||||||
|
if (!status) {
|
||||||
|
WIIUSE_DEBUG("Disabled IR cameras for wiimote id %i.", wm->unid);
|
||||||
|
wiiuse_set_report_type(wm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enable IR, set sensitivity */
|
||||||
|
buf = 0x08;
|
||||||
|
wiiuse_write_data(wm, WM_REG_IR, &buf, 1);
|
||||||
|
|
||||||
|
/* wait for the wiimote to catch up */
|
||||||
|
#ifndef WIN32
|
||||||
|
usleep(50000);
|
||||||
|
#else
|
||||||
|
Sleep(50);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* write sensitivity blocks */
|
||||||
|
wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (byte*)block1, 9);
|
||||||
|
wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (byte*)block2, 2);
|
||||||
|
|
||||||
|
/* set the IR mode */
|
||||||
|
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP))
|
||||||
|
buf = WM_IR_TYPE_BASIC;
|
||||||
|
else
|
||||||
|
buf = WM_IR_TYPE_EXTENDED;
|
||||||
|
wiiuse_write_data(wm, WM_REG_IR_MODENUM, &buf, 1);
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
usleep(50000);
|
||||||
|
#else
|
||||||
|
Sleep(50);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* set the wiimote report type */
|
||||||
|
wiiuse_set_report_type(wm);
|
||||||
|
|
||||||
|
WIIUSE_DEBUG("Enabled IR camera for wiimote id %i (sensitivity level %i).", wm->unid, ir_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the IR sensitivity settings.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param block1 [out] Pointer to where block1 will be set.
|
||||||
|
* @param block2 [out] Pointer to where block2 will be set.
|
||||||
|
*
|
||||||
|
* @return Returns the sensitivity level.
|
||||||
|
*/
|
||||||
|
static int get_ir_sens(struct wiimote_t* wm, char** block1, char** block2) {
|
||||||
|
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL1)) {
|
||||||
|
*block1 = WM_IR_BLOCK1_LEVEL1;
|
||||||
|
*block2 = WM_IR_BLOCK2_LEVEL1;
|
||||||
|
return 1;
|
||||||
|
} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL2)) {
|
||||||
|
*block1 = WM_IR_BLOCK1_LEVEL2;
|
||||||
|
*block2 = WM_IR_BLOCK2_LEVEL2;
|
||||||
|
return 2;
|
||||||
|
} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL3)) {
|
||||||
|
*block1 = WM_IR_BLOCK1_LEVEL3;
|
||||||
|
*block2 = WM_IR_BLOCK2_LEVEL3;
|
||||||
|
return 3;
|
||||||
|
} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL4)) {
|
||||||
|
*block1 = WM_IR_BLOCK1_LEVEL4;
|
||||||
|
*block2 = WM_IR_BLOCK2_LEVEL4;
|
||||||
|
return 4;
|
||||||
|
} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL5)) {
|
||||||
|
*block1 = WM_IR_BLOCK1_LEVEL5;
|
||||||
|
*block2 = WM_IR_BLOCK2_LEVEL5;
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
*block1 = NULL;
|
||||||
|
*block2 = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the virtual screen resolution for IR tracking.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param status 1 to enable, 0 to disable.
|
||||||
|
*/
|
||||||
|
void wiiuse_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y) {
|
||||||
|
if (!wm) return;
|
||||||
|
|
||||||
|
wm->ir.vres[0] = (x-1);
|
||||||
|
wm->ir.vres[1] = (y-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the XY position for the IR cursor.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
*/
|
||||||
|
void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos) {
|
||||||
|
if (!wm) return;
|
||||||
|
|
||||||
|
wm->ir.pos = pos;
|
||||||
|
|
||||||
|
switch (pos) {
|
||||||
|
|
||||||
|
case WIIUSE_IR_ABOVE:
|
||||||
|
wm->ir.offset[0] = 0;
|
||||||
|
|
||||||
|
if (wm->ir.aspect == WIIUSE_ASPECT_16_9)
|
||||||
|
wm->ir.offset[1] = WM_ASPECT_16_9_Y/2 - 70;
|
||||||
|
else if (wm->ir.aspect == WIIUSE_ASPECT_4_3)
|
||||||
|
wm->ir.offset[1] = WM_ASPECT_4_3_Y/2 - 100;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
case WIIUSE_IR_BELOW:
|
||||||
|
wm->ir.offset[0] = 0;
|
||||||
|
|
||||||
|
if (wm->ir.aspect == WIIUSE_ASPECT_16_9)
|
||||||
|
wm->ir.offset[1] = -WM_ASPECT_16_9_Y/2 + 100;
|
||||||
|
else if (wm->ir.aspect == WIIUSE_ASPECT_4_3)
|
||||||
|
wm->ir.offset[1] = -WM_ASPECT_4_3_Y/2 + 70;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the aspect ratio of the TV/monitor.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param aspect Either WIIUSE_ASPECT_16_9 or WIIUSE_ASPECT_4_3
|
||||||
|
*/
|
||||||
|
void wiiuse_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect) {
|
||||||
|
if (!wm) return;
|
||||||
|
|
||||||
|
wm->ir.aspect = aspect;
|
||||||
|
|
||||||
|
if (aspect == WIIUSE_ASPECT_4_3) {
|
||||||
|
wm->ir.vres[0] = WM_ASPECT_4_3_X;
|
||||||
|
wm->ir.vres[1] = WM_ASPECT_4_3_Y;
|
||||||
|
} else {
|
||||||
|
wm->ir.vres[0] = WM_ASPECT_16_9_X;
|
||||||
|
wm->ir.vres[1] = WM_ASPECT_16_9_Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reset the position offsets */
|
||||||
|
wiiuse_set_ir_position(wm, wm->ir.pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the IR sensitivity.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param level 1-5, same as Wii system sensitivity setting.
|
||||||
|
*
|
||||||
|
* If the level is < 1, then level will be set to 1.
|
||||||
|
* If the level is > 5, then level will be set to 5.
|
||||||
|
*/
|
||||||
|
void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level) {
|
||||||
|
char* block1 = NULL;
|
||||||
|
char* block2 = NULL;
|
||||||
|
|
||||||
|
if (!wm) return;
|
||||||
|
|
||||||
|
if (level > 5) level = 5;
|
||||||
|
if (level < 1) level = 1;
|
||||||
|
|
||||||
|
WIIMOTE_DISABLE_STATE(wm, (WIIMOTE_STATE_IR_SENS_LVL1 |
|
||||||
|
WIIMOTE_STATE_IR_SENS_LVL2 |
|
||||||
|
WIIMOTE_STATE_IR_SENS_LVL3 |
|
||||||
|
WIIMOTE_STATE_IR_SENS_LVL4 |
|
||||||
|
WIIMOTE_STATE_IR_SENS_LVL5));
|
||||||
|
|
||||||
|
switch (level) {
|
||||||
|
case 1:
|
||||||
|
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL1);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL2);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL3);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL4);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL5);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the new sensitivity */
|
||||||
|
get_ir_sens(wm, &block1, &block2);
|
||||||
|
|
||||||
|
wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (byte*)block1, 9);
|
||||||
|
wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (byte*)block2, 2);
|
||||||
|
|
||||||
|
WIIUSE_DEBUG("Set IR sensitivity to level %i (unid %i)", level, wm->unid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate the data from the IR spots. Basic IR mode.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param data Data returned by the wiimote for the IR spots.
|
||||||
|
*/
|
||||||
|
void calculate_basic_ir(struct wiimote_t* wm, byte* data) {
|
||||||
|
struct ir_dot_t* dot = wm->ir.dot;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dot[0].rx = 1023 - (data[0] | ((data[2] & 0x30) << 4));
|
||||||
|
dot[0].ry = data[1] | ((data[2] & 0xC0) << 2);
|
||||||
|
|
||||||
|
dot[1].rx = 1023 - (data[3] | ((data[2] & 0x03) << 8));
|
||||||
|
dot[1].ry = data[4] | ((data[2] & 0x0C) << 6);
|
||||||
|
|
||||||
|
dot[2].rx = 1023 - (data[5] | ((data[7] & 0x30) << 4));
|
||||||
|
dot[2].ry = data[6] | ((data[7] & 0xC0) << 2);
|
||||||
|
|
||||||
|
dot[3].rx = 1023 - (data[8] | ((data[7] & 0x03) << 8));
|
||||||
|
dot[3].ry = data[9] | ((data[7] & 0x0C) << 6);
|
||||||
|
|
||||||
|
/* set each IR spot to visible if spot is in range */
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
if (dot[i].ry == 1023)
|
||||||
|
dot[i].visible = 0;
|
||||||
|
else {
|
||||||
|
dot[i].visible = 1;
|
||||||
|
dot[i].size = 0; /* since we don't know the size, set it as 0 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interpret_ir_data(wm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate the data from the IR spots. Extended IR mode.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param data Data returned by the wiimote for the IR spots.
|
||||||
|
*/
|
||||||
|
void calculate_extended_ir(struct wiimote_t* wm, byte* data) {
|
||||||
|
struct ir_dot_t* dot = wm->ir.dot;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
dot[i].rx = 1023 - (data[3*i] | ((data[(3*i)+2] & 0x30) << 4));
|
||||||
|
dot[i].ry = data[(3*i)+1] | ((data[(3*i)+2] & 0xC0) << 2);
|
||||||
|
|
||||||
|
dot[i].size = data[(3*i)+2] & 0x0F;
|
||||||
|
|
||||||
|
/* if in range set to visible */
|
||||||
|
if (dot[i].ry == 1023)
|
||||||
|
dot[i].visible = 0;
|
||||||
|
else
|
||||||
|
dot[i].visible = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
interpret_ir_data(wm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interpret IR data into more user friendly variables.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
*/
|
||||||
|
static void interpret_ir_data(struct wiimote_t* wm) {
|
||||||
|
struct ir_dot_t* dot = wm->ir.dot;
|
||||||
|
int i;
|
||||||
|
float roll = 0.0f;
|
||||||
|
int last_num_dots = wm->ir.num_dots;
|
||||||
|
|
||||||
|
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC))
|
||||||
|
roll = wm->orient.roll;
|
||||||
|
|
||||||
|
/* count visible dots */
|
||||||
|
wm->ir.num_dots = 0;
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
if (dot[i].visible)
|
||||||
|
wm->ir.num_dots++;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (wm->ir.num_dots) {
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
wm->ir.state = 0;
|
||||||
|
|
||||||
|
/* reset the dot ordering */
|
||||||
|
for (i = 0; i < 4; ++i)
|
||||||
|
dot[i].order = 0;
|
||||||
|
|
||||||
|
wm->ir.x = 0;
|
||||||
|
wm->ir.y = 0;
|
||||||
|
wm->ir.z = 0.0f;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
fix_rotated_ir_dots(wm->ir.dot, roll);
|
||||||
|
|
||||||
|
if (wm->ir.state < 2) {
|
||||||
|
/*
|
||||||
|
* Only 1 known dot, so use just that.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
if (dot[i].visible) {
|
||||||
|
wm->ir.x = dot[i].x;
|
||||||
|
wm->ir.y = dot[i].y;
|
||||||
|
|
||||||
|
wm->ir.ax = wm->ir.x;
|
||||||
|
wm->ir.ay = wm->ir.y;
|
||||||
|
|
||||||
|
/* can't calculate yaw because we don't have the distance */
|
||||||
|
//wm->orient.yaw = calc_yaw(&wm->ir);
|
||||||
|
|
||||||
|
ir_convert_to_vres(&wm->ir.x, &wm->ir.y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Only see 1 dot but know theres 2.
|
||||||
|
* Try to estimate where the other one
|
||||||
|
* should be and use that.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
if (dot[i].visible) {
|
||||||
|
int ox = 0;
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
if (dot[i].order == 1)
|
||||||
|
/* visible is the left dot - estimate where the right is */
|
||||||
|
ox = dot[i].x + wm->ir.distance;
|
||||||
|
else if (dot[i].order == 2)
|
||||||
|
/* visible is the right dot - estimate where the left is */
|
||||||
|
ox = dot[i].x - wm->ir.distance;
|
||||||
|
|
||||||
|
x = ((signed int)dot[i].x + ox) / 2;
|
||||||
|
y = dot[i].y;
|
||||||
|
|
||||||
|
wm->ir.ax = x;
|
||||||
|
wm->ir.ay = y;
|
||||||
|
wm->orient.yaw = calc_yaw(&wm->ir);
|
||||||
|
|
||||||
|
if (ir_correct_for_bounds(&x, &y, wm->ir.aspect, wm->ir.offset[0], wm->ir.offset[1])) {
|
||||||
|
ir_convert_to_vres(&x, &y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]);
|
||||||
|
wm->ir.x = x;
|
||||||
|
wm->ir.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Two (or more) dots known and seen.
|
||||||
|
* Average them together to estimate the true location.
|
||||||
|
*/
|
||||||
|
int x, y;
|
||||||
|
wm->ir.state = 2;
|
||||||
|
|
||||||
|
fix_rotated_ir_dots(wm->ir.dot, roll);
|
||||||
|
|
||||||
|
/* if there is at least 1 new dot, reorder them all */
|
||||||
|
if (wm->ir.num_dots > last_num_dots) {
|
||||||
|
reorder_ir_dots(dot);
|
||||||
|
wm->ir.x = 0;
|
||||||
|
wm->ir.y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
wm->ir.distance = ir_distance(dot);
|
||||||
|
wm->ir.z = 1023 - wm->ir.distance;
|
||||||
|
|
||||||
|
get_ir_dot_avg(wm->ir.dot, &x, &y);
|
||||||
|
|
||||||
|
wm->ir.ax = x;
|
||||||
|
wm->ir.ay = y;
|
||||||
|
wm->orient.yaw = calc_yaw(&wm->ir);
|
||||||
|
|
||||||
|
if (ir_correct_for_bounds(&x, &y, wm->ir.aspect, wm->ir.offset[0], wm->ir.offset[1])) {
|
||||||
|
ir_convert_to_vres(&x, &y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]);
|
||||||
|
wm->ir.x = x;
|
||||||
|
wm->ir.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_WIIUSE_DEBUG
|
||||||
|
{
|
||||||
|
int ir_level;
|
||||||
|
WIIUSE_GET_IR_SENSITIVITY(wm, &ir_level);
|
||||||
|
WIIUSE_DEBUG("IR sensitivity: %i", ir_level);
|
||||||
|
WIIUSE_DEBUG("IR visible dots: %i", wm->ir.num_dots);
|
||||||
|
for (i = 0; i < 4; ++i)
|
||||||
|
if (dot[i].visible)
|
||||||
|
WIIUSE_DEBUG("IR[%i][order %i] (%.3i, %.3i) -> (%.3i, %.3i)", i, dot[i].order, dot[i].rx, dot[i].ry, dot[i].x, dot[i].y);
|
||||||
|
WIIUSE_DEBUG("IR[absolute]: (%i, %i)", wm->ir.x, wm->ir.y);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Fix the rotation of the IR dots.
|
||||||
|
*
|
||||||
|
* @param dot An array of 4 ir_dot_t objects.
|
||||||
|
* @param ang The roll angle to correct by (-180, 180)
|
||||||
|
*
|
||||||
|
* If there is roll then the dots are rotated
|
||||||
|
* around the origin and give a false cursor
|
||||||
|
* position. Correct for the roll.
|
||||||
|
*
|
||||||
|
* If the accelerometer is off then obviously
|
||||||
|
* this will not do anything and the cursor
|
||||||
|
* position may be inaccurate.
|
||||||
|
*/
|
||||||
|
static void fix_rotated_ir_dots(struct ir_dot_t* dot, float ang) {
|
||||||
|
float s, c;
|
||||||
|
int x, y;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!ang) {
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
dot[i].x = dot[i].rx;
|
||||||
|
dot[i].y = dot[i].ry;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = sin(DEGREE_TO_RAD(ang));
|
||||||
|
c = cos(DEGREE_TO_RAD(ang));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [ cos(theta) -sin(theta) ][ ir->rx ]
|
||||||
|
* [ sin(theta) cos(theta) ][ ir->ry ]
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
if (!dot[i].visible)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
x = dot[i].rx - (1024/2);
|
||||||
|
y = dot[i].ry - (768/2);
|
||||||
|
|
||||||
|
dot[i].x = (c * x) + (-s * y);
|
||||||
|
dot[i].y = (s * x) + (c * y);
|
||||||
|
|
||||||
|
dot[i].x += (1024/2);
|
||||||
|
dot[i].y += (768/2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Average IR dots.
|
||||||
|
*
|
||||||
|
* @param dot An array of 4 ir_dot_t objects.
|
||||||
|
* @param x [out] Average X
|
||||||
|
* @param y [out] Average Y
|
||||||
|
*/
|
||||||
|
static void get_ir_dot_avg(struct ir_dot_t* dot, int* x, int* y) {
|
||||||
|
int vis = 0, i = 0;
|
||||||
|
|
||||||
|
*x = 0;
|
||||||
|
*y = 0;
|
||||||
|
|
||||||
|
for (; i < 4; ++i) {
|
||||||
|
if (dot[i].visible) {
|
||||||
|
*x += dot[i].x;
|
||||||
|
*y += dot[i].y;
|
||||||
|
++vis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*x /= vis;
|
||||||
|
*y /= vis;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reorder the IR dots.
|
||||||
|
*
|
||||||
|
* @param dot An array of 4 ir_dot_t objects.
|
||||||
|
*/
|
||||||
|
static void reorder_ir_dots(struct ir_dot_t* dot) {
|
||||||
|
int i, j, order;
|
||||||
|
|
||||||
|
/* reset the dot ordering */
|
||||||
|
for (i = 0; i < 4; ++i)
|
||||||
|
dot[i].order = 0;
|
||||||
|
|
||||||
|
for (order = 1; order < 5; ++order) {
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
for (; !dot[i].visible || dot[i].order; ++i)
|
||||||
|
if (i > 4)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (j = 0; j < 4; ++j) {
|
||||||
|
if (dot[j].visible && !dot[j].order && (dot[j].x < dot[i].x))
|
||||||
|
i = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
dot[i].order = order;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate the distance between the first 2 visible IR dots.
|
||||||
|
*
|
||||||
|
* @param dot An array of 4 ir_dot_t objects.
|
||||||
|
*/
|
||||||
|
static float ir_distance(struct ir_dot_t* dot) {
|
||||||
|
int i1, i2;
|
||||||
|
int xd, yd;
|
||||||
|
|
||||||
|
for (i1 = 0; i1 < 4; ++i1)
|
||||||
|
if (dot[i1].visible)
|
||||||
|
break;
|
||||||
|
if (i1 == 4)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
for (i2 = i1+1; i2 < 4; ++i2)
|
||||||
|
if (dot[i2].visible)
|
||||||
|
break;
|
||||||
|
if (i2 == 4)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
xd = dot[i2].x - dot[i1].x;
|
||||||
|
yd = dot[i2].y - dot[i1].y;
|
||||||
|
|
||||||
|
return sqrt(xd*xd + yd*yd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Correct for the IR bounding box.
|
||||||
|
*
|
||||||
|
* @param x [out] The current X, it will be updated if valid.
|
||||||
|
* @param y [out] The current Y, it will be updated if valid.
|
||||||
|
* @param aspect Aspect ratio of the screen.
|
||||||
|
* @param offset_x The X offset of the bounding box.
|
||||||
|
* @param offset_y The Y offset of the bounding box.
|
||||||
|
*
|
||||||
|
* @return Returns 1 if the point is valid and was updated.
|
||||||
|
*
|
||||||
|
* Nintendo was smart with this bit. They sacrifice a little
|
||||||
|
* precision for a big increase in usability.
|
||||||
|
*/
|
||||||
|
static int ir_correct_for_bounds(int* x, int* y, enum aspect_t aspect, int offset_x, int offset_y) {
|
||||||
|
int x0, y0;
|
||||||
|
int xs, ys;
|
||||||
|
|
||||||
|
if (aspect == WIIUSE_ASPECT_16_9) {
|
||||||
|
xs = WM_ASPECT_16_9_X;
|
||||||
|
ys = WM_ASPECT_16_9_Y;
|
||||||
|
} else {
|
||||||
|
xs = WM_ASPECT_4_3_X;
|
||||||
|
ys = WM_ASPECT_4_3_Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
x0 = ((1024 - xs) / 2) + offset_x;
|
||||||
|
y0 = ((768 - ys) / 2) + offset_y;
|
||||||
|
|
||||||
|
if ((*x >= x0)
|
||||||
|
&& (*x <= (x0 + xs))
|
||||||
|
&& (*y >= y0)
|
||||||
|
&& (*y <= (y0 + ys)))
|
||||||
|
{
|
||||||
|
*x -= offset_x;
|
||||||
|
*y -= offset_y;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interpolate the point to the user defined virtual screen resolution.
|
||||||
|
*/
|
||||||
|
static void ir_convert_to_vres(int* x, int* y, enum aspect_t aspect, int vx, int vy) {
|
||||||
|
int xs, ys;
|
||||||
|
|
||||||
|
if (aspect == WIIUSE_ASPECT_16_9) {
|
||||||
|
xs = WM_ASPECT_16_9_X;
|
||||||
|
ys = WM_ASPECT_16_9_Y;
|
||||||
|
} else {
|
||||||
|
xs = WM_ASPECT_4_3_X;
|
||||||
|
ys = WM_ASPECT_4_3_Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
*x -= ((1024-xs)/2);
|
||||||
|
*y -= ((768-ys)/2);
|
||||||
|
|
||||||
|
*x = (*x / (float)xs) * vx;
|
||||||
|
*y = (*y / (float)ys) * vy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate yaw given the IR data.
|
||||||
|
*
|
||||||
|
* @param ir IR data structure.
|
||||||
|
*/
|
||||||
|
float calc_yaw(struct ir_t* ir) {
|
||||||
|
float x;
|
||||||
|
|
||||||
|
x = ir->ax - 512;
|
||||||
|
x = x * (ir->z / 1024.0f);
|
||||||
|
|
||||||
|
return RAD_TO_DEGREE( atanf(x / ir->z) );
|
||||||
|
}
|
||||||
56
src/ir.h
Normal file
56
src/ir.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Handles IR data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IR_H_INCLUDED
|
||||||
|
#define IR_H_INCLUDED
|
||||||
|
|
||||||
|
#include "wiiuse_internal.h"
|
||||||
|
|
||||||
|
#define WII_VRES_X 560
|
||||||
|
#define WII_VRES_Y 340
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void calculate_basic_ir(struct wiimote_t* wm, byte* data);
|
||||||
|
void calculate_extended_ir(struct wiimote_t* wm, byte* data);
|
||||||
|
float calc_yaw(struct ir_t* ir);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // IR_H_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
191
src/msvc/wiiuse.dsp
Normal file
191
src/msvc/wiiuse.dsp
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
# Microsoft Developer Studio Project File - Name="wiiuse" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||||
|
|
||||||
|
CFG=wiiuse - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "wiiuse.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "wiiuse.mak" CFG="wiiuse - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "wiiuse - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "wiiuse - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
MTL=midl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "wiiuse - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WIIUSE_EXPORTS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WIIUSE_EXPORTS" /YX /FD /c
|
||||||
|
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib hid.lib setupapi.lib /nologo /dll /machine:I386
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "wiiuse - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WIIUSE_EXPORTS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WIIUSE_EXPORTS" /D "WITH_WIIUSE_DEBUG" /YX /FD /GZ /c
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib hid.lib setupapi.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "wiiuse - Win32 Release"
|
||||||
|
# Name "wiiuse - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\classic.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\dynamics.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\events.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\guitar_hero_3.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\io.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\io_nix.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\io_win.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\ir.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\nunchuk.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\wiiuse.c
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\classic.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\definitions.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\dynamics.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\events.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\guitar_hero_3.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\io.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\ir.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\nunchuk.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\os.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\wiiuse.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\wiiuse_internal.h
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Resource Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\CHANGELOG
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
||||||
29
src/msvc/wiiuse.dsw
Normal file
29
src/msvc/wiiuse.dsw
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||||
|
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "wiiuse"=".\wiiuse.dsp" - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Global:
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<3>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
BIN
src/msvc/wiiuse.ncb
Normal file
BIN
src/msvc/wiiuse.ncb
Normal file
Binary file not shown.
BIN
src/msvc/wiiuse.opt
Normal file
BIN
src/msvc/wiiuse.opt
Normal file
Binary file not shown.
210
src/nunchuk.c
Normal file
210
src/nunchuk.c
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Nunchuk expansion device.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "definitions.h"
|
||||||
|
#include "wiiuse_internal.h"
|
||||||
|
#include "dynamics.h"
|
||||||
|
#include "events.h"
|
||||||
|
#include "nunchuk.h"
|
||||||
|
|
||||||
|
static void nunchuk_pressed_buttons(struct nunchuk_t* nc, byte now);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle the handshake data from the nunchuk.
|
||||||
|
*
|
||||||
|
* @param nc A pointer to a nunchuk_t structure.
|
||||||
|
* @param data The data read in from the device.
|
||||||
|
* @param len The length of the data block, in bytes.
|
||||||
|
*
|
||||||
|
* @return Returns 1 if handshake was successful, 0 if not.
|
||||||
|
*/
|
||||||
|
int nunchuk_handshake(struct wiimote_t* wm, struct nunchuk_t* nc, byte* data, unsigned short len) {
|
||||||
|
int i;
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
nc->btns = 0;
|
||||||
|
nc->btns_held = 0;
|
||||||
|
nc->btns_released = 0;
|
||||||
|
|
||||||
|
/* set the smoothing to the same as the wiimote */
|
||||||
|
nc->flags = &wm->flags;
|
||||||
|
nc->accel_calib.st_alpha = wm->accel_calib.st_alpha;
|
||||||
|
|
||||||
|
/* decrypt data */
|
||||||
|
for (i = 0; i < len; ++i)
|
||||||
|
data[i] = (data[i] ^ 0x17) + 0x17;
|
||||||
|
|
||||||
|
if (data[offset] == 0xFF) {
|
||||||
|
/*
|
||||||
|
* Sometimes the data returned here is not correct.
|
||||||
|
* This might happen because the wiimote is lagging
|
||||||
|
* behind our initialization sequence.
|
||||||
|
* To fix this just request the handshake again.
|
||||||
|
*
|
||||||
|
* Other times it's just the first 16 bytes are 0xFF,
|
||||||
|
* but since the next 16 bytes are the same, just use
|
||||||
|
* those.
|
||||||
|
*/
|
||||||
|
if (data[offset + 16] == 0xFF) {
|
||||||
|
/* get the calibration data */
|
||||||
|
byte* handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
|
||||||
|
|
||||||
|
WIIUSE_DEBUG("Nunchuk handshake appears invalid, trying again.");
|
||||||
|
wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
offset += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
nc->accel_calib.cal_zero.x = data[offset + 0];
|
||||||
|
nc->accel_calib.cal_zero.y = data[offset + 1];
|
||||||
|
nc->accel_calib.cal_zero.z = data[offset + 2];
|
||||||
|
nc->accel_calib.cal_g.x = data[offset + 4];
|
||||||
|
nc->accel_calib.cal_g.y = data[offset + 5];
|
||||||
|
nc->accel_calib.cal_g.z = data[offset + 6];
|
||||||
|
nc->js.max.x = data[offset + 8];
|
||||||
|
nc->js.min.x = data[offset + 9];
|
||||||
|
nc->js.center.x = data[offset + 10];
|
||||||
|
nc->js.max.y = data[offset + 11];
|
||||||
|
nc->js.min.y = data[offset + 12];
|
||||||
|
nc->js.center.y = data[offset + 13];
|
||||||
|
|
||||||
|
/* default the thresholds to the same as the wiimote */
|
||||||
|
nc->orient_threshold = wm->orient_threshold;
|
||||||
|
nc->accel_threshold = wm->accel_threshold;
|
||||||
|
|
||||||
|
/* handshake done */
|
||||||
|
wm->exp.type = EXP_NUNCHUK;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The nunchuk disconnected.
|
||||||
|
*
|
||||||
|
* @param nc A pointer to a nunchuk_t structure.
|
||||||
|
*/
|
||||||
|
void nunchuk_disconnected(struct nunchuk_t* nc) {
|
||||||
|
memset(nc, 0, sizeof(struct nunchuk_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle nunchuk event.
|
||||||
|
*
|
||||||
|
* @param nc A pointer to a nunchuk_t structure.
|
||||||
|
* @param msg The message specified in the event packet.
|
||||||
|
*/
|
||||||
|
void nunchuk_event(struct nunchuk_t* nc, byte* msg) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* decrypt data */
|
||||||
|
for (i = 0; i < 6; ++i)
|
||||||
|
msg[i] = (msg[i] ^ 0x17) + 0x17;
|
||||||
|
|
||||||
|
/* get button states */
|
||||||
|
nunchuk_pressed_buttons(nc, msg[5]);
|
||||||
|
|
||||||
|
/* calculate joystick state */
|
||||||
|
calc_joystick_state(&nc->js, msg[0], msg[1]);
|
||||||
|
|
||||||
|
/* calculate orientation */
|
||||||
|
nc->accel.x = msg[2];
|
||||||
|
nc->accel.y = msg[3];
|
||||||
|
nc->accel.z = msg[4];
|
||||||
|
|
||||||
|
calculate_orientation(&nc->accel_calib, &nc->accel, &nc->orient, NUNCHUK_IS_FLAG_SET(nc, WIIUSE_SMOOTHING));
|
||||||
|
calculate_gforce(&nc->accel_calib, &nc->accel, &nc->gforce);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Find what buttons are pressed.
|
||||||
|
*
|
||||||
|
* @param nc Pointer to a nunchuk_t structure.
|
||||||
|
* @param msg The message byte specified in the event packet.
|
||||||
|
*/
|
||||||
|
static void nunchuk_pressed_buttons(struct nunchuk_t* nc, byte now) {
|
||||||
|
/* message is inverted (0 is active, 1 is inactive) */
|
||||||
|
now = ~now & NUNCHUK_BUTTON_ALL;
|
||||||
|
|
||||||
|
/* pressed now & were pressed, then held */
|
||||||
|
nc->btns_held = (now & nc->btns);
|
||||||
|
|
||||||
|
/* were pressed or were held & not pressed now, then released */
|
||||||
|
nc->btns_released = ((nc->btns | nc->btns_held) & ~now);
|
||||||
|
|
||||||
|
/* buttons pressed now */
|
||||||
|
nc->btns = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the orientation event threshold for the nunchuk.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure with a nunchuk attached.
|
||||||
|
* @param threshold The decimal place that should be considered a significant change.
|
||||||
|
*
|
||||||
|
* See wiiuse_set_orient_threshold() for details.
|
||||||
|
*/
|
||||||
|
void wiiuse_set_nunchuk_orient_threshold(struct wiimote_t* wm, float threshold) {
|
||||||
|
if (!wm) return;
|
||||||
|
|
||||||
|
wm->exp.nunchuk.orient_threshold = threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the accelerometer event threshold for the nunchuk.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure with a nunchuk attached.
|
||||||
|
* @param threshold The decimal place that should be considered a significant change.
|
||||||
|
*
|
||||||
|
* See wiiuse_set_orient_threshold() for details.
|
||||||
|
*/
|
||||||
|
void wiiuse_set_nunchuk_accel_threshold(struct wiimote_t* wm, int threshold) {
|
||||||
|
if (!wm) return;
|
||||||
|
|
||||||
|
wm->exp.nunchuk.accel_threshold = threshold;
|
||||||
|
}
|
||||||
53
src/nunchuk.h
Normal file
53
src/nunchuk.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Nunchuk expansion device.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NUNCHUK_H_INCLUDED
|
||||||
|
#define NUNCHUK_H_INCLUDED
|
||||||
|
|
||||||
|
#include "wiiuse_internal.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int nunchuk_handshake(struct wiimote_t* wm, struct nunchuk_t* nc, byte* data, unsigned short len);
|
||||||
|
|
||||||
|
void nunchuk_disconnected(struct nunchuk_t* nc);
|
||||||
|
|
||||||
|
void nunchuk_event(struct nunchuk_t* nc, byte* msg);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // NUNCHUK_H_INCLUDED
|
||||||
56
src/os.h
Normal file
56
src/os.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Operating system related definitions.
|
||||||
|
*
|
||||||
|
* This file is an attempt to separate operating system
|
||||||
|
* dependent functions and choose what should be used
|
||||||
|
* at compile time.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OS_H_INCLUDED
|
||||||
|
#define OS_H_INCLUDED
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
/* windows */
|
||||||
|
#define isnan(x) _isnan(x)
|
||||||
|
#define isinf(x) !_finite(x)
|
||||||
|
|
||||||
|
/* disable warnings I don't care about */
|
||||||
|
#pragma warning(disable:4244) /* possible loss of data conversion */
|
||||||
|
#pragma warning(disable:4273) /* inconsistent dll linkage */
|
||||||
|
#pragma warning(disable:4217)
|
||||||
|
#else
|
||||||
|
/* nix */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif // OS_H_INCLUDED
|
||||||
764
src/wiiuse.c
Normal file
764
src/wiiuse.c
Normal file
@@ -0,0 +1,764 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief General wiimote operations.
|
||||||
|
*
|
||||||
|
* The file includes functions that handle general
|
||||||
|
* tasks. Most of these are functions that are part
|
||||||
|
* of the API.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
#include <Winsock2.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "definitions.h"
|
||||||
|
#include "wiiuse_internal.h"
|
||||||
|
#include "events.h"
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
static int g_banner = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @breif Returns the version of the library.
|
||||||
|
*/
|
||||||
|
const char* wiiuse_version() {
|
||||||
|
return WIIUSE_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clean up wiimote_t array created by wiiuse_init()
|
||||||
|
*/
|
||||||
|
void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (!wm)
|
||||||
|
return;
|
||||||
|
|
||||||
|
WIIUSE_INFO("wiiuse clean up...");
|
||||||
|
|
||||||
|
for (; i < wiimotes; ++i) {
|
||||||
|
wiiuse_disconnect(wm[i]);
|
||||||
|
free(wm[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(wm);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize an array of wiimote structures.
|
||||||
|
*
|
||||||
|
* @param wiimotes Number of wiimote_t structures to create.
|
||||||
|
*
|
||||||
|
* @return An array of initialized wiimote_t structures.
|
||||||
|
*
|
||||||
|
* @see wiiuse_connect()
|
||||||
|
*
|
||||||
|
* The array returned by this function can be passed to various
|
||||||
|
* functions, including wiiuse_connect().
|
||||||
|
*/
|
||||||
|
struct wiimote_t** wiiuse_init(int wiimotes) {
|
||||||
|
int i = 0;
|
||||||
|
struct wiimote_t** wm = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Please do not remove this banner.
|
||||||
|
* GPL asks that you please leave output credits intact.
|
||||||
|
* Thank you.
|
||||||
|
*
|
||||||
|
* This banner is only displayed once so that if you need
|
||||||
|
* to call this function again it won't be intrusive.
|
||||||
|
*/
|
||||||
|
if (!g_banner) {
|
||||||
|
printf( "wiiuse v" WIIUSE_VERSION " loaded.\n"
|
||||||
|
" By: Michael Laforest <thepara[at]gmail{dot}com>\n"
|
||||||
|
" http://wiiuse.net http://wiiuse.sf.net\n");
|
||||||
|
g_banner = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wiimotes)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
wm = malloc(sizeof(struct wiimote_t*) * wiimotes);
|
||||||
|
|
||||||
|
for (i = 0; i < wiimotes; ++i) {
|
||||||
|
wm[i] = malloc(sizeof(struct wiimote_t));
|
||||||
|
memset(wm[i], 0, sizeof(struct wiimote_t));
|
||||||
|
|
||||||
|
wm[i]->unid = i+1;
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
wm[i]->bdaddr = *BDADDR_ANY;
|
||||||
|
wm[i]->out_sock = -1;
|
||||||
|
wm[i]->in_sock = -1;
|
||||||
|
#else
|
||||||
|
wm[i]->dev_handle = 0;
|
||||||
|
wm[i]->stack = WIIUSE_STACK_UNKNOWN;
|
||||||
|
wm[i]->normal_timeout = WIIMOTE_DEFAULT_TIMEOUT;
|
||||||
|
wm[i]->exp_timeout = WIIMOTE_EXP_TIMEOUT;
|
||||||
|
wm[i]->timeout = wm[i]->normal_timeout;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wm[i]->state = WIIMOTE_INIT_STATES;
|
||||||
|
wm[i]->flags = WIIUSE_INIT_FLAGS;
|
||||||
|
|
||||||
|
wm[i]->event = WIIUSE_NONE;
|
||||||
|
|
||||||
|
wm[i]->exp.type = EXP_NONE;
|
||||||
|
|
||||||
|
wiiuse_set_aspect_ratio(wm[i], WIIUSE_ASPECT_4_3);
|
||||||
|
wiiuse_set_ir_position(wm[i], WIIUSE_IR_ABOVE);
|
||||||
|
|
||||||
|
wm[i]->orient_threshold = 0.5f;
|
||||||
|
wm[i]->accel_threshold = 5;
|
||||||
|
|
||||||
|
wm[i]->accel_calib.st_alpha = WIIUSE_DEFAULT_SMOOTH_ALPHA;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The wiimote disconnected.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
*/
|
||||||
|
void wiiuse_disconnected(struct wiimote_t* wm) {
|
||||||
|
if (!wm) return;
|
||||||
|
|
||||||
|
WIIUSE_INFO("Wiimote disconnected [id %i].", wm->unid);
|
||||||
|
|
||||||
|
/* disable the connected flag */
|
||||||
|
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
|
||||||
|
|
||||||
|
/* reset a bunch of stuff */
|
||||||
|
#ifndef WIN32
|
||||||
|
wm->out_sock = -1;
|
||||||
|
wm->in_sock = -1;
|
||||||
|
#else
|
||||||
|
wm->dev_handle = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wm->leds = 0;
|
||||||
|
wm->state = WIIMOTE_INIT_STATES;
|
||||||
|
wm->read_req = NULL;
|
||||||
|
wm->handshake_state = 0;
|
||||||
|
wm->btns = 0;
|
||||||
|
wm->btns_held = 0;
|
||||||
|
wm->btns_released = 0;
|
||||||
|
memset(wm->event_buf, 0, sizeof(wm->event_buf));
|
||||||
|
|
||||||
|
wm->event = WIIUSE_DISCONNECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable or disable the rumble.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param status 1 to enable, 0 to disable.
|
||||||
|
*/
|
||||||
|
void wiiuse_rumble(struct wiimote_t* wm, int status) {
|
||||||
|
byte buf;
|
||||||
|
|
||||||
|
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* make sure to keep the current lit leds */
|
||||||
|
buf = wm->leds;
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
WIIUSE_DEBUG("Starting rumble...");
|
||||||
|
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_RUMBLE);
|
||||||
|
buf |= 0x01;
|
||||||
|
} else {
|
||||||
|
WIIUSE_DEBUG("Stopping rumble...");
|
||||||
|
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_RUMBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* preserve IR state */
|
||||||
|
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR))
|
||||||
|
buf |= 0x04;
|
||||||
|
|
||||||
|
wiiuse_send(wm, WM_CMD_RUMBLE, &buf, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Toggle the state of the rumble.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
*/
|
||||||
|
void wiiuse_toggle_rumble(struct wiimote_t* wm) {
|
||||||
|
if (!wm) return;
|
||||||
|
|
||||||
|
wiiuse_rumble(wm, !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the enabled LEDs.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param leds What LEDs to enable.
|
||||||
|
*
|
||||||
|
* \a leds is a bitwise or of WIIMOTE_LED_1, WIIMOTE_LED_2, WIIMOTE_LED_3, or WIIMOTE_LED_4.
|
||||||
|
*/
|
||||||
|
void wiiuse_set_leds(struct wiimote_t* wm, int leds) {
|
||||||
|
byte buf;
|
||||||
|
|
||||||
|
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* remove the lower 4 bits because they control rumble */
|
||||||
|
wm->leds = (leds & 0xF0);
|
||||||
|
|
||||||
|
/* make sure if the rumble is on that we keep it on */
|
||||||
|
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE))
|
||||||
|
wm->leds |= 0x01;
|
||||||
|
|
||||||
|
buf = wm->leds;
|
||||||
|
|
||||||
|
wiiuse_send(wm, WM_CMD_LED, &buf, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set if the wiimote should report motion sensing.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param status 1 to enable, 0 to disable.
|
||||||
|
*
|
||||||
|
* Since reporting motion sensing sends a lot of data,
|
||||||
|
* the wiimote saves power by not transmitting it
|
||||||
|
* by default.
|
||||||
|
*/
|
||||||
|
void wiiuse_motion_sensing(struct wiimote_t* wm, int status) {
|
||||||
|
if (status)
|
||||||
|
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_ACC);
|
||||||
|
else
|
||||||
|
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_ACC);
|
||||||
|
|
||||||
|
wiiuse_set_report_type(wm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the report type based on the current wiimote state.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
*
|
||||||
|
* @return The report type sent.
|
||||||
|
*
|
||||||
|
* The wiimote reports formatted packets depending on the
|
||||||
|
* report type that was last requested. This function will
|
||||||
|
* update the type of report that should be sent based on
|
||||||
|
* the current state of the device.
|
||||||
|
*/
|
||||||
|
int wiiuse_set_report_type(struct wiimote_t* wm) {
|
||||||
|
byte buf[2];
|
||||||
|
int motion, exp, ir;
|
||||||
|
|
||||||
|
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
buf[0] = (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_CONTINUOUS) ? 0x04 : 0x00); /* set to 0x04 for continuous reporting */
|
||||||
|
buf[1] = 0x00;
|
||||||
|
|
||||||
|
/* if rumble is enabled, make sure we keep it */
|
||||||
|
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE))
|
||||||
|
buf[0] |= 0x01;
|
||||||
|
|
||||||
|
motion = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC);
|
||||||
|
exp = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP);
|
||||||
|
ir = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR);
|
||||||
|
|
||||||
|
if (motion && ir && exp) buf[1] = WM_RPT_BTN_ACC_IR_EXP;
|
||||||
|
else if (motion && exp) buf[1] = WM_RPT_BTN_ACC_EXP;
|
||||||
|
else if (motion && ir) buf[1] = WM_RPT_BTN_ACC_IR;
|
||||||
|
else if (ir && exp) buf[1] = WM_RPT_BTN_IR_EXP;
|
||||||
|
else if (ir) buf[1] = WM_RPT_BTN_ACC_IR;
|
||||||
|
else if (exp) buf[1] = WM_RPT_BTN_EXP;
|
||||||
|
else if (motion) buf[1] = WM_RPT_BTN_ACC;
|
||||||
|
else buf[1] = WM_RPT_BTN;
|
||||||
|
|
||||||
|
WIIUSE_DEBUG("Setting report type: 0x%x", buf[1]);
|
||||||
|
|
||||||
|
exp = wiiuse_send(wm, WM_CMD_REPORT_TYPE, buf, 2);
|
||||||
|
if (exp <= 0)
|
||||||
|
return exp;
|
||||||
|
|
||||||
|
return buf[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read data from the wiimote (callback version).
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param read_cb Function pointer to call when the data arrives from the wiimote.
|
||||||
|
* @param buffer An allocated buffer to store the data as it arrives from the wiimote.
|
||||||
|
* Must be persistent in memory and large enough to hold the data.
|
||||||
|
* @param addr The address of wiimote memory to read from.
|
||||||
|
* @param len The length of the block to be read.
|
||||||
|
*
|
||||||
|
* The library can only handle one data read request at a time
|
||||||
|
* because it must keep track of the buffer and other
|
||||||
|
* events that are specific to that request. So if a request
|
||||||
|
* has already been made, subsequent requests will be added
|
||||||
|
* to a pending list and be sent out when the previous
|
||||||
|
* finishes.
|
||||||
|
*/
|
||||||
|
int wiiuse_read_data_cb(struct wiimote_t* wm, wiiuse_read_cb read_cb, byte* buffer, unsigned int addr, unsigned short len) {
|
||||||
|
struct read_req_t* req;
|
||||||
|
|
||||||
|
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
|
||||||
|
return 0;
|
||||||
|
if (!buffer || !len || !read_cb)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* make this request structure */
|
||||||
|
req = (struct read_req_t*)malloc(sizeof(struct read_req_t));
|
||||||
|
req->cb = read_cb;
|
||||||
|
req->buf = buffer;
|
||||||
|
req->addr = addr;
|
||||||
|
req->size = len;
|
||||||
|
req->wait = len;
|
||||||
|
req->dirty = 0;
|
||||||
|
req->next = NULL;
|
||||||
|
|
||||||
|
/* add this to the request list */
|
||||||
|
if (!wm->read_req) {
|
||||||
|
/* root node */
|
||||||
|
wm->read_req = req;
|
||||||
|
|
||||||
|
WIIUSE_DEBUG("Data read request can be sent out immediately.");
|
||||||
|
|
||||||
|
/* send the request out immediately */
|
||||||
|
wiiuse_send_next_pending_read_request(wm);
|
||||||
|
} else {
|
||||||
|
struct read_req_t* nptr = wm->read_req;
|
||||||
|
for (; nptr->next; nptr = nptr->next);
|
||||||
|
nptr->next = req;
|
||||||
|
|
||||||
|
WIIUSE_DEBUG("Added pending data read request.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read data from the wiimote (event version).
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param buffer An allocated buffer to store the data as it arrives from the wiimote.
|
||||||
|
* Must be persistent in memory and large enough to hold the data.
|
||||||
|
* @param addr The address of wiimote memory to read from.
|
||||||
|
* @param len The length of the block to be read.
|
||||||
|
*
|
||||||
|
* The library can only handle one data read request at a time
|
||||||
|
* because it must keep track of the buffer and other
|
||||||
|
* events that are specific to that request. So if a request
|
||||||
|
* has already been made, subsequent requests will be added
|
||||||
|
* to a pending list and be sent out when the previous
|
||||||
|
* finishes.
|
||||||
|
*/
|
||||||
|
int wiiuse_read_data(struct wiimote_t* wm, byte* buffer, unsigned int addr, unsigned short len) {
|
||||||
|
struct read_req_t* req;
|
||||||
|
|
||||||
|
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
|
||||||
|
return 0;
|
||||||
|
if (!buffer || !len)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* make this request structure */
|
||||||
|
req = (struct read_req_t*)malloc(sizeof(struct read_req_t));
|
||||||
|
req->cb = NULL;
|
||||||
|
req->buf = buffer;
|
||||||
|
req->addr = addr;
|
||||||
|
req->size = len;
|
||||||
|
req->wait = len;
|
||||||
|
req->dirty = 0;
|
||||||
|
req->next = NULL;
|
||||||
|
|
||||||
|
/* add this to the request list */
|
||||||
|
if (!wm->read_req) {
|
||||||
|
/* root node */
|
||||||
|
wm->read_req = req;
|
||||||
|
|
||||||
|
WIIUSE_DEBUG("Data read request can be sent out immediately.");
|
||||||
|
|
||||||
|
/* send the request out immediately */
|
||||||
|
wiiuse_send_next_pending_read_request(wm);
|
||||||
|
} else {
|
||||||
|
struct read_req_t* nptr = wm->read_req;
|
||||||
|
for (; nptr->next; nptr = nptr->next);
|
||||||
|
nptr->next = req;
|
||||||
|
|
||||||
|
WIIUSE_DEBUG("Added pending data read request.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send the next pending data read request to the wiimote.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
*
|
||||||
|
* @see wiiuse_read_data()
|
||||||
|
*
|
||||||
|
* This function is not part of the wiiuse API.
|
||||||
|
*/
|
||||||
|
void wiiuse_send_next_pending_read_request(struct wiimote_t* wm) {
|
||||||
|
byte buf[6];
|
||||||
|
struct read_req_t* req;
|
||||||
|
|
||||||
|
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
|
||||||
|
return;
|
||||||
|
if (!wm->read_req) return;
|
||||||
|
|
||||||
|
/* skip over dirty ones since they have already been read */
|
||||||
|
req = wm->read_req;
|
||||||
|
while (req && req->dirty)
|
||||||
|
req = req->next;
|
||||||
|
if (!req)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* the offset is in big endian */
|
||||||
|
*(int*)(buf) = BIG_ENDIAN_LONG(req->addr);
|
||||||
|
|
||||||
|
/* the length is in big endian */
|
||||||
|
*(short*)(buf + 4) = BIG_ENDIAN_SHORT(req->size);
|
||||||
|
|
||||||
|
WIIUSE_DEBUG("Request read at address: 0x%x length: %i", req->addr, req->size);
|
||||||
|
wiiuse_send(wm, WM_CMD_READ_DATA, buf, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Request the wiimote controller status.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
*
|
||||||
|
* Controller status includes: battery level, LED status, expansions
|
||||||
|
*/
|
||||||
|
void wiiuse_status(struct wiimote_t* wm) {
|
||||||
|
byte buf = 0;
|
||||||
|
|
||||||
|
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
|
||||||
|
return;
|
||||||
|
|
||||||
|
WIIUSE_DEBUG("Requested wiimote status.");
|
||||||
|
|
||||||
|
wiiuse_send(wm, WM_CMD_CTRL_STATUS, &buf, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Find a wiimote_t structure by its unique identifier.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param wiimotes The number of wiimote_t structures in \a wm.
|
||||||
|
* @param unid The unique identifier to search for.
|
||||||
|
*
|
||||||
|
* @return Pointer to a wiimote_t structure, or NULL if not found.
|
||||||
|
*/
|
||||||
|
struct wiimote_t* wiiuse_get_by_id(struct wiimote_t** wm, int wiimotes, int unid) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (; i < wiimotes; ++i) {
|
||||||
|
if (wm[i]->unid == unid)
|
||||||
|
return wm[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write data to the wiimote.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param addr The address to write to.
|
||||||
|
* @param data The data to be written to the memory location.
|
||||||
|
* @param len The length of the block to be written.
|
||||||
|
*/
|
||||||
|
int wiiuse_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len) {
|
||||||
|
byte buf[21] = {0}; /* the payload is always 23 */
|
||||||
|
|
||||||
|
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
|
||||||
|
return 0;
|
||||||
|
if (!data || !len)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
WIIUSE_DEBUG("Writing %i bytes to memory location 0x%x...", len, addr);
|
||||||
|
|
||||||
|
#ifdef WITH_WIIUSE_DEBUG
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
printf("Write data is: ");
|
||||||
|
for (; i < len; ++i)
|
||||||
|
printf("%x ", data[i]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* the offset is in big endian */
|
||||||
|
*(int*)(buf) = BIG_ENDIAN_LONG(addr);
|
||||||
|
|
||||||
|
/* length */
|
||||||
|
*(byte*)(buf + 4) = len;
|
||||||
|
|
||||||
|
/* data */
|
||||||
|
memcpy(buf + 5, data, len);
|
||||||
|
|
||||||
|
wiiuse_send(wm, WM_CMD_WRITE_DATA, buf, 21);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send a packet to the wiimote.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param report_type The report type to send (WIIMOTE_CMD_LED, WIIMOTE_CMD_RUMBLE, etc). Found in wiiuse.h
|
||||||
|
* @param msg The payload.
|
||||||
|
* @param len Length of the payload in bytes.
|
||||||
|
*
|
||||||
|
* This function should replace any write()s directly to the wiimote device.
|
||||||
|
*/
|
||||||
|
int wiiuse_send(struct wiimote_t* wm, byte report_type, byte* msg, int len) {
|
||||||
|
byte buf[32]; /* no payload is better than this */
|
||||||
|
int rumble = 0;
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
buf[0] = WM_SET_REPORT | WM_BT_OUTPUT;
|
||||||
|
buf[1] = report_type;
|
||||||
|
#else
|
||||||
|
buf[0] = report_type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (report_type) {
|
||||||
|
case WM_CMD_LED:
|
||||||
|
case WM_CMD_RUMBLE:
|
||||||
|
case WM_CMD_CTRL_STATUS:
|
||||||
|
{
|
||||||
|
/* Rumble flag for: 0x11, 0x13, 0x14, 0x15, 0x19 or 0x1a */
|
||||||
|
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE))
|
||||||
|
rumble = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
memcpy(buf+2, msg, len);
|
||||||
|
if (rumble)
|
||||||
|
buf[2] |= 0x01;
|
||||||
|
#else
|
||||||
|
memcpy(buf+1, msg, len);
|
||||||
|
if (rumble)
|
||||||
|
buf[1] |= 0x01;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_WIIUSE_DEBUG
|
||||||
|
{
|
||||||
|
int x = 2;
|
||||||
|
printf("[DEBUG] (id %i) SEND: (%x) %.2x ", wm->unid, buf[0], buf[1]);
|
||||||
|
#ifndef WIN32
|
||||||
|
for (; x < len+2; ++x)
|
||||||
|
#else
|
||||||
|
for (; x < len+1; ++x)
|
||||||
|
#endif
|
||||||
|
printf("%.2x ", buf[x]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
return wiiuse_io_write(wm, buf, len+2);
|
||||||
|
#else
|
||||||
|
return wiiuse_io_write(wm, buf, len+1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set flags for the specified wiimote.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param enable Flags to enable.
|
||||||
|
* @param disable Flags to disable.
|
||||||
|
*
|
||||||
|
* @return The flags set after 'enable' and 'disable' have been applied.
|
||||||
|
*
|
||||||
|
* The values 'enable' and 'disable' may be any flags OR'ed together.
|
||||||
|
* Flags are defined in wiiuse.h.
|
||||||
|
*/
|
||||||
|
int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable) {
|
||||||
|
if (!wm) return 0;
|
||||||
|
|
||||||
|
/* remove mutually exclusive flags */
|
||||||
|
enable &= ~disable;
|
||||||
|
disable &= ~enable;
|
||||||
|
|
||||||
|
wm->flags |= enable;
|
||||||
|
wm->flags &= ~disable;
|
||||||
|
|
||||||
|
return wm->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the wiimote smoothing alpha value.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param alpha The alpha value to set. Between 0 and 1.
|
||||||
|
*
|
||||||
|
* @return Returns the old alpha value.
|
||||||
|
*
|
||||||
|
* The alpha value is between 0 and 1 and is used in an exponential
|
||||||
|
* smoothing algorithm.
|
||||||
|
*
|
||||||
|
* Smoothing is only performed if the WIIMOTE_USE_SMOOTHING is set.
|
||||||
|
*/
|
||||||
|
float wiiuse_set_smooth_alpha(struct wiimote_t* wm, float alpha) {
|
||||||
|
float old;
|
||||||
|
|
||||||
|
if (!wm) return 0.0f;
|
||||||
|
|
||||||
|
old = wm->accel_calib.st_alpha;
|
||||||
|
|
||||||
|
wm->accel_calib.st_alpha = alpha;
|
||||||
|
|
||||||
|
/* if there is a nunchuk set that too */
|
||||||
|
if (wm->exp.type == EXP_NUNCHUK)
|
||||||
|
wm->exp.nunchuk.accel_calib.st_alpha = alpha;
|
||||||
|
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the bluetooth stack type to use.
|
||||||
|
*
|
||||||
|
* @param wm Array of wiimote_t structures.
|
||||||
|
* @param wiimotes Number of objects in the wm array.
|
||||||
|
* @param type The type of bluetooth stack to use.
|
||||||
|
*/
|
||||||
|
void wiiuse_set_bluetooth_stack(struct wiimote_t** wm, int wiimotes, enum win_bt_stack_t type) {
|
||||||
|
#ifdef WIN32
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!wm) return;
|
||||||
|
|
||||||
|
for (i = 0; i < wiimotes; ++i)
|
||||||
|
wm[i]->stack = type;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the orientation event threshold.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param threshold The decimal place that should be considered a significant change.
|
||||||
|
*
|
||||||
|
* If threshold is 0.01, and any angle changes by 0.01 then a significant change
|
||||||
|
* has occured and the event callback will be invoked. If threshold is 1 then
|
||||||
|
* the angle has to change by a full degree to generate an event.
|
||||||
|
*/
|
||||||
|
void wiiuse_set_orient_threshold(struct wiimote_t* wm, float threshold) {
|
||||||
|
if (!wm) return;
|
||||||
|
|
||||||
|
wm->orient_threshold = threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the accelerometer event threshold.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param threshold The decimal place that should be considered a significant change.
|
||||||
|
*/
|
||||||
|
void wiiuse_set_accel_threshold(struct wiimote_t* wm, int threshold) {
|
||||||
|
if (!wm) return;
|
||||||
|
|
||||||
|
wm->accel_threshold = threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Try to resync with the wiimote by starting a new handshake.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
*/
|
||||||
|
void wiiuse_resync(struct wiimote_t* wm) {
|
||||||
|
if (!wm) return;
|
||||||
|
|
||||||
|
wm->handshake_state = 0;
|
||||||
|
wiiuse_handshake(wm, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the normal and expansion handshake timeouts.
|
||||||
|
*
|
||||||
|
* @param wm Array of wiimote_t structures.
|
||||||
|
* @param wiimotes Number of objects in the wm array.
|
||||||
|
* @param normal_timeout The timeout in milliseconds for a normal read.
|
||||||
|
* @param exp_timeout The timeout in millisecondsd to wait for an expansion handshake.
|
||||||
|
*/
|
||||||
|
void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, byte normal_timeout, byte exp_timeout) {
|
||||||
|
#ifdef WIN32
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!wm) return;
|
||||||
|
|
||||||
|
for (i = 0; i < wiimotes; ++i) {
|
||||||
|
wm[i]->normal_timeout = normal_timeout;
|
||||||
|
wm[i]->exp_timeout = exp_timeout;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
653
src/wiiuse.h
Normal file
653
src/wiiuse.h
Normal file
@@ -0,0 +1,653 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @brief API header file.
|
||||||
|
*
|
||||||
|
* If this file is included from inside the wiiuse source
|
||||||
|
* and not from a third party program, then wiimote_internal.h
|
||||||
|
* is also included which extends this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WIIUSE_H_INCLUDED
|
||||||
|
#define WIIUSE_H_INCLUDED
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* windows */
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
/* nix */
|
||||||
|
#include <bluetooth/bluetooth.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIIUSE_INTERNAL_H_INCLUDED
|
||||||
|
#define WCONST
|
||||||
|
#else
|
||||||
|
#define WCONST const
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* led bit masks */
|
||||||
|
#define WIIMOTE_LED_NONE 0x00
|
||||||
|
#define WIIMOTE_LED_1 0x10
|
||||||
|
#define WIIMOTE_LED_2 0x20
|
||||||
|
#define WIIMOTE_LED_3 0x40
|
||||||
|
#define WIIMOTE_LED_4 0x80
|
||||||
|
|
||||||
|
/* button codes */
|
||||||
|
#define WIIMOTE_BUTTON_TWO 0x0001
|
||||||
|
#define WIIMOTE_BUTTON_ONE 0x0002
|
||||||
|
#define WIIMOTE_BUTTON_B 0x0004
|
||||||
|
#define WIIMOTE_BUTTON_A 0x0008
|
||||||
|
#define WIIMOTE_BUTTON_MINUS 0x0010
|
||||||
|
#define WIIMOTE_BUTTON_ZACCEL_BIT6 0x0020
|
||||||
|
#define WIIMOTE_BUTTON_ZACCEL_BIT7 0x0040
|
||||||
|
#define WIIMOTE_BUTTON_HOME 0x0080
|
||||||
|
#define WIIMOTE_BUTTON_LEFT 0x0100
|
||||||
|
#define WIIMOTE_BUTTON_RIGHT 0x0200
|
||||||
|
#define WIIMOTE_BUTTON_DOWN 0x0400
|
||||||
|
#define WIIMOTE_BUTTON_UP 0x0800
|
||||||
|
#define WIIMOTE_BUTTON_PLUS 0x1000
|
||||||
|
#define WIIMOTE_BUTTON_ZACCEL_BIT4 0x2000
|
||||||
|
#define WIIMOTE_BUTTON_ZACCEL_BIT5 0x4000
|
||||||
|
#define WIIMOTE_BUTTON_UNKNOWN 0x8000
|
||||||
|
#define WIIMOTE_BUTTON_ALL 0x1F9F
|
||||||
|
|
||||||
|
/* nunchul button codes */
|
||||||
|
#define NUNCHUK_BUTTON_Z 0x01
|
||||||
|
#define NUNCHUK_BUTTON_C 0x02
|
||||||
|
#define NUNCHUK_BUTTON_ALL 0x03
|
||||||
|
|
||||||
|
/* classic controller button codes */
|
||||||
|
#define CLASSIC_CTRL_BUTTON_UP 0x0001
|
||||||
|
#define CLASSIC_CTRL_BUTTON_LEFT 0x0002
|
||||||
|
#define CLASSIC_CTRL_BUTTON_ZR 0x0004
|
||||||
|
#define CLASSIC_CTRL_BUTTON_X 0x0008
|
||||||
|
#define CLASSIC_CTRL_BUTTON_A 0x0010
|
||||||
|
#define CLASSIC_CTRL_BUTTON_Y 0x0020
|
||||||
|
#define CLASSIC_CTRL_BUTTON_B 0x0040
|
||||||
|
#define CLASSIC_CTRL_BUTTON_ZL 0x0080
|
||||||
|
#define CLASSIC_CTRL_BUTTON_FULL_R 0x0200
|
||||||
|
#define CLASSIC_CTRL_BUTTON_PLUS 0x0400
|
||||||
|
#define CLASSIC_CTRL_BUTTON_HOME 0x0800
|
||||||
|
#define CLASSIC_CTRL_BUTTON_MINUS 0x1000
|
||||||
|
#define CLASSIC_CTRL_BUTTON_FULL_L 0x2000
|
||||||
|
#define CLASSIC_CTRL_BUTTON_DOWN 0x4000
|
||||||
|
#define CLASSIC_CTRL_BUTTON_RIGHT 0x8000
|
||||||
|
#define CLASSIC_CTRL_BUTTON_ALL 0xFEFF
|
||||||
|
|
||||||
|
/* guitar hero 3 button codes */
|
||||||
|
#define GUITAR_HERO_3_BUTTON_STRUM_UP 0x0001
|
||||||
|
#define GUITAR_HERO_3_BUTTON_YELLOW 0x0008
|
||||||
|
#define GUITAR_HERO_3_BUTTON_GREEN 0x0010
|
||||||
|
#define GUITAR_HERO_3_BUTTON_BLUE 0x0020
|
||||||
|
#define GUITAR_HERO_3_BUTTON_RED 0x0040
|
||||||
|
#define GUITAR_HERO_3_BUTTON_ORANGE 0x0080
|
||||||
|
#define GUITAR_HERO_3_BUTTON_PLUS 0x0400
|
||||||
|
#define GUITAR_HERO_3_BUTTON_MINUS 0x1000
|
||||||
|
#define GUITAR_HERO_3_BUTTON_STRUM_DOWN 0x4000
|
||||||
|
#define GUITAR_HERO_3_BUTTON_ALL 0xFEFF
|
||||||
|
|
||||||
|
|
||||||
|
/* wiimote option flags */
|
||||||
|
#define WIIUSE_SMOOTHING 0x01
|
||||||
|
#define WIIUSE_CONTINUOUS 0x02
|
||||||
|
#define WIIUSE_ORIENT_THRESH 0x04
|
||||||
|
#define WIIUSE_INIT_FLAGS (WIIUSE_SMOOTHING | WIIUSE_ORIENT_THRESH)
|
||||||
|
|
||||||
|
#define WIIUSE_ORIENT_PRECISION 100.0f
|
||||||
|
|
||||||
|
/* expansion codes */
|
||||||
|
#define EXP_NONE 0
|
||||||
|
#define EXP_NUNCHUK 1
|
||||||
|
#define EXP_CLASSIC 2
|
||||||
|
#define EXP_GUITAR_HERO_3 3
|
||||||
|
|
||||||
|
/* IR correction types */
|
||||||
|
typedef enum ir_position_t {
|
||||||
|
WIIUSE_IR_ABOVE,
|
||||||
|
WIIUSE_IR_BELOW
|
||||||
|
} ir_position_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if a button is pressed.
|
||||||
|
* @param dev Pointer to a wiimote_t or expansion structure.
|
||||||
|
* @param button The button you are interested in.
|
||||||
|
* @return 1 if the button is pressed, 0 if not.
|
||||||
|
*/
|
||||||
|
#define IS_PRESSED(dev, button) ((dev->btns & button) == button)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if a button is being held.
|
||||||
|
* @param dev Pointer to a wiimote_t or expansion structure.
|
||||||
|
* @param button The button you are interested in.
|
||||||
|
* @return 1 if the button is held, 0 if not.
|
||||||
|
*/
|
||||||
|
#define IS_HELD(dev, button) ((dev->btns_held & button) == button)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if a button is released on this event. \n\n
|
||||||
|
* This does not mean the button is not pressed, it means \n
|
||||||
|
* this button was just now released.
|
||||||
|
* @param dev Pointer to a wiimote_t or expansion structure.
|
||||||
|
* @param button The button you are interested in.
|
||||||
|
* @return 1 if the button is released, 0 if not.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define IS_RELEASED(dev, button) ((dev->btns_released & button) == button)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if a button has just been pressed this event.
|
||||||
|
* @param dev Pointer to a wiimote_t or expansion structure.
|
||||||
|
* @param button The button you are interested in.
|
||||||
|
* @return 1 if the button is pressed, 0 if not.
|
||||||
|
*/
|
||||||
|
#define IS_JUST_PRESSED(dev, button) (IS_PRESSED(dev, button) && !IS_HELD(dev, button))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return the IR sensitivity level.
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param lvl [out] Pointer to an int that will hold the level setting.
|
||||||
|
* If no level is set 'lvl' will be set to 0.
|
||||||
|
*/
|
||||||
|
#define WIIUSE_GET_IR_SENSITIVITY(dev, lvl) \
|
||||||
|
do { \
|
||||||
|
if ((wm->state & 0x0200) == 0x0200) *lvl = 1; \
|
||||||
|
else if ((wm->state & 0x0400) == 0x0400) *lvl = 2; \
|
||||||
|
else if ((wm->state & 0x0800) == 0x0800) *lvl = 3; \
|
||||||
|
else if ((wm->state & 0x1000) == 0x1000) *lvl = 4; \
|
||||||
|
else if ((wm->state & 0x2000) == 0x2000) *lvl = 5; \
|
||||||
|
else *lvl = 0; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define WIIUSE_USING_ACC(wm) ((wm->state & 0x020) == 0x020)
|
||||||
|
#define WIIUSE_USING_EXP(wm) ((wm->state & 0x040) == 0x040)
|
||||||
|
#define WIIUSE_USING_IR(wm) ((wm->state & 0x080) == 0x080)
|
||||||
|
#define WIIUSE_USING_SPEAKER(wm) ((wm->state & 0x100) == 0x100)
|
||||||
|
|
||||||
|
#define WIIUSE_IS_LED_SET(wm, num) ((wm->leds & WIIMOTE_LED_##num) == WIIMOTE_LED_##num)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Largest known payload is 21 bytes.
|
||||||
|
* Add 2 for the prefix and round up to a power of 2.
|
||||||
|
*/
|
||||||
|
#define MAX_PAYLOAD 32
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is left over from an old hack, but it may actually
|
||||||
|
* be a useful feature to keep so it wasn't removed.
|
||||||
|
*/
|
||||||
|
#ifdef WIN32
|
||||||
|
#define WIIMOTE_DEFAULT_TIMEOUT 10
|
||||||
|
#define WIIMOTE_EXP_TIMEOUT 10
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef unsigned char byte;
|
||||||
|
typedef char sbyte;
|
||||||
|
|
||||||
|
struct wiimote_t;
|
||||||
|
struct vec3b_t;
|
||||||
|
struct orient_t;
|
||||||
|
struct gforce_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback that handles a read event.
|
||||||
|
*
|
||||||
|
* @param wm Pointer to a wiimote_t structure.
|
||||||
|
* @param data Pointer to the filled data block.
|
||||||
|
* @param len Length in bytes of the data block.
|
||||||
|
*
|
||||||
|
* @see wiiuse_init()
|
||||||
|
*
|
||||||
|
* A registered function of this type is called automatically by the wiiuse
|
||||||
|
* library when the wiimote has returned the full data requested by a previous
|
||||||
|
* call to wiiuse_read_data().
|
||||||
|
*/
|
||||||
|
typedef void (*wiiuse_read_cb)(struct wiimote_t* wm, byte* data, unsigned short len);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct read_req_t
|
||||||
|
* @brief Data read request structure.
|
||||||
|
*/
|
||||||
|
struct read_req_t {
|
||||||
|
wiiuse_read_cb cb; /**< read data callback */
|
||||||
|
byte* buf; /**< buffer where read data is written */
|
||||||
|
unsigned int addr; /**< the offset that the read started at */
|
||||||
|
unsigned short size; /**< the length of the data read */
|
||||||
|
unsigned short wait; /**< num bytes still needed to finish read */
|
||||||
|
byte dirty; /**< set to 1 if not using callback and needs to be cleaned up */
|
||||||
|
|
||||||
|
struct read_req_t* next; /**< next read request in the queue */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct vec2b_t
|
||||||
|
* @brief Unsigned x,y byte vector.
|
||||||
|
*/
|
||||||
|
typedef struct vec2b_t {
|
||||||
|
byte x, y;
|
||||||
|
} vec2b_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct vec3b_t
|
||||||
|
* @brief Unsigned x,y,z byte vector.
|
||||||
|
*/
|
||||||
|
typedef struct vec3b_t {
|
||||||
|
byte x, y, z;
|
||||||
|
} vec3b_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct vec3f_t
|
||||||
|
* @brief Signed x,y,z float struct.
|
||||||
|
*/
|
||||||
|
typedef struct vec3f_t {
|
||||||
|
float x, y, z;
|
||||||
|
} vec3f_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct orient_t
|
||||||
|
* @brief Orientation struct.
|
||||||
|
*
|
||||||
|
* Yaw, pitch, and roll range from -180 to 180 degrees.
|
||||||
|
*/
|
||||||
|
typedef struct orient_t {
|
||||||
|
float roll; /**< roll, this may be smoothed if enabled */
|
||||||
|
float pitch; /**< pitch, this may be smoothed if enabled */
|
||||||
|
float yaw;
|
||||||
|
|
||||||
|
float a_roll; /**< absolute roll, unsmoothed */
|
||||||
|
float a_pitch; /**< absolute pitch, unsmoothed */
|
||||||
|
} orient_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct gforce_t
|
||||||
|
* @brief Gravity force struct.
|
||||||
|
*/
|
||||||
|
typedef struct gforce_t {
|
||||||
|
float x, y, z;
|
||||||
|
} gforce_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct accel_t
|
||||||
|
* @brief Accelerometer struct. For any device with an accelerometer.
|
||||||
|
*/
|
||||||
|
typedef struct accel_t {
|
||||||
|
struct vec3b_t cal_zero; /**< zero calibration */
|
||||||
|
struct vec3b_t cal_g; /**< 1g difference around 0cal */
|
||||||
|
|
||||||
|
float st_roll; /**< last smoothed roll value */
|
||||||
|
float st_pitch; /**< last smoothed roll pitch */
|
||||||
|
float st_alpha; /**< alpha value for smoothing [0-1] */
|
||||||
|
} accel_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct ir_dot_t
|
||||||
|
* @brief A single IR source.
|
||||||
|
*/
|
||||||
|
typedef struct ir_dot_t {
|
||||||
|
byte visible; /**< if the IR source is visible */
|
||||||
|
|
||||||
|
unsigned int x; /**< interpolated X coordinate */
|
||||||
|
unsigned int y; /**< interpolated Y coordinate */
|
||||||
|
|
||||||
|
short rx; /**< raw X coordinate (0-1023) */
|
||||||
|
short ry; /**< raw Y coordinate (0-767) */
|
||||||
|
|
||||||
|
byte order; /**< increasing order by x-axis value */
|
||||||
|
|
||||||
|
byte size; /**< size of the IR dot (0-15) */
|
||||||
|
} ir_dot_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum aspect_t
|
||||||
|
* @brief Screen aspect ratio.
|
||||||
|
*/
|
||||||
|
typedef enum aspect_t {
|
||||||
|
WIIUSE_ASPECT_4_3,
|
||||||
|
WIIUSE_ASPECT_16_9
|
||||||
|
} aspect_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct ir_t
|
||||||
|
* @brief IR struct. Hold all data related to the IR tracking.
|
||||||
|
*/
|
||||||
|
typedef struct ir_t {
|
||||||
|
struct ir_dot_t dot[4]; /**< IR dots */
|
||||||
|
byte num_dots; /**< number of dots at this time */
|
||||||
|
|
||||||
|
enum aspect_t aspect; /**< aspect ratio of the screen */
|
||||||
|
|
||||||
|
enum ir_position_t pos; /**< IR sensor bar position */
|
||||||
|
|
||||||
|
unsigned int vres[2]; /**< IR virtual screen resolution */
|
||||||
|
int offset[2]; /**< IR XY correction offset */
|
||||||
|
int state; /**< keeps track of the IR state */
|
||||||
|
|
||||||
|
int ax; /**< absolute X coordinate */
|
||||||
|
int ay; /**< absolute Y coordinate */
|
||||||
|
|
||||||
|
int x; /**< calculated X coordinate */
|
||||||
|
int y; /**< calculated Y coordinate */
|
||||||
|
|
||||||
|
float distance; /**< pixel distance between first 2 dots*/
|
||||||
|
float z; /**< calculated distance */
|
||||||
|
} ir_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct joystick_t
|
||||||
|
* @brief Joystick calibration structure.
|
||||||
|
*
|
||||||
|
* The angle \a ang is relative to the positive y-axis into quadrant I
|
||||||
|
* and ranges from 0 to 360 degrees. So if the joystick is held straight
|
||||||
|
* upwards then angle is 0 degrees. If it is held to the right it is 90,
|
||||||
|
* down is 180, and left is 270.
|
||||||
|
*
|
||||||
|
* The magnitude \a mag is the distance from the center to where the
|
||||||
|
* joystick is being held. The magnitude ranges from 0 to 1.
|
||||||
|
* If the joystick is only slightly tilted from the center the magnitude
|
||||||
|
* will be low, but if it is closer to the outter edge the value will
|
||||||
|
* be higher.
|
||||||
|
*/
|
||||||
|
typedef struct joystick_t {
|
||||||
|
struct vec2b_t max; /**< maximum joystick values */
|
||||||
|
struct vec2b_t min; /**< minimum joystick values */
|
||||||
|
struct vec2b_t center; /**< center joystick values */
|
||||||
|
|
||||||
|
float ang; /**< angle the joystick is being held */
|
||||||
|
float mag; /**< magnitude of the joystick (range 0-1) */
|
||||||
|
} joystick_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct nunchuk_t
|
||||||
|
* @brief Nunchuk expansion device.
|
||||||
|
*/
|
||||||
|
typedef struct nunchuk_t {
|
||||||
|
struct accel_t accel_calib; /**< nunchuk accelerometer calibration */
|
||||||
|
struct joystick_t js; /**< joystick calibration */
|
||||||
|
|
||||||
|
int* flags; /**< options flag (points to wiimote_t.flags) */
|
||||||
|
|
||||||
|
byte btns; /**< what buttons have just been pressed */
|
||||||
|
byte btns_held; /**< what buttons are being held down */
|
||||||
|
byte btns_released; /**< what buttons were just released this */
|
||||||
|
|
||||||
|
float orient_threshold; /**< threshold for orient to generate an event */
|
||||||
|
int accel_threshold; /**< threshold for accel to generate an event */
|
||||||
|
|
||||||
|
struct vec3b_t accel; /**< current raw acceleration data */
|
||||||
|
struct orient_t orient; /**< current orientation on each axis */
|
||||||
|
struct gforce_t gforce; /**< current gravity forces on each axis */
|
||||||
|
} nunchuk_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct classic_ctrl_t
|
||||||
|
* @brief Classic controller expansion device.
|
||||||
|
*/
|
||||||
|
typedef struct classic_ctrl_t {
|
||||||
|
short btns; /**< what buttons have just been pressed */
|
||||||
|
short btns_held; /**< what buttons are being held down */
|
||||||
|
short btns_released; /**< what buttons were just released this */
|
||||||
|
|
||||||
|
float r_shoulder; /**< right shoulder button (range 0-1) */
|
||||||
|
float l_shoulder; /**< left shoulder button (range 0-1) */
|
||||||
|
|
||||||
|
struct joystick_t ljs; /**< left joystick calibration */
|
||||||
|
struct joystick_t rjs; /**< right joystick calibration */
|
||||||
|
} classic_ctrl_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct guitar_hero_3_t
|
||||||
|
* @brief Guitar Hero 3 expansion device.
|
||||||
|
*/
|
||||||
|
typedef struct guitar_hero_3_t {
|
||||||
|
short btns; /**< what buttons have just been pressed */
|
||||||
|
short btns_held; /**< what buttons are being held down */
|
||||||
|
short btns_released; /**< what buttons were just released this */
|
||||||
|
|
||||||
|
float whammy_bar; /**< whammy bar (range 0-1) */
|
||||||
|
|
||||||
|
struct joystick_t js; /**< joystick calibration */
|
||||||
|
} guitar_hero_3_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct expansion_t
|
||||||
|
* @brief Generic expansion device plugged into wiimote.
|
||||||
|
*/
|
||||||
|
typedef struct expansion_t {
|
||||||
|
int type; /**< type of expansion attached */
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct nunchuk_t nunchuk;
|
||||||
|
struct classic_ctrl_t classic;
|
||||||
|
struct guitar_hero_3_t gh3;
|
||||||
|
};
|
||||||
|
} expansion_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum win32_bt_stack_t
|
||||||
|
* @brief Available bluetooth stacks for Windows.
|
||||||
|
*/
|
||||||
|
typedef enum win_bt_stack_t {
|
||||||
|
WIIUSE_STACK_UNKNOWN,
|
||||||
|
WIIUSE_STACK_MS,
|
||||||
|
WIIUSE_STACK_BLUESOLEIL
|
||||||
|
} win_bt_stack_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct wiimote_state_t
|
||||||
|
* @brief Significant data from the previous event.
|
||||||
|
*/
|
||||||
|
typedef struct wiimote_state_t {
|
||||||
|
/* expansion_t */
|
||||||
|
float exp_ljs_ang;
|
||||||
|
float exp_rjs_ang;
|
||||||
|
float exp_ljs_mag;
|
||||||
|
float exp_rjs_mag;
|
||||||
|
unsigned short exp_btns;
|
||||||
|
struct orient_t exp_orient;
|
||||||
|
struct vec3b_t exp_accel;
|
||||||
|
float exp_r_shoulder;
|
||||||
|
float exp_l_shoulder;
|
||||||
|
|
||||||
|
/* ir_t */
|
||||||
|
int ir_ax;
|
||||||
|
int ir_ay;
|
||||||
|
float ir_distance;
|
||||||
|
|
||||||
|
struct orient_t orient;
|
||||||
|
unsigned short btns;
|
||||||
|
|
||||||
|
struct vec3b_t accel;
|
||||||
|
} wiimote_state_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum WIIUSE_EVENT_TYPE
|
||||||
|
* @brief Events that wiiuse can generate from a poll.
|
||||||
|
*/
|
||||||
|
typedef enum WIIUSE_EVENT_TYPE {
|
||||||
|
WIIUSE_NONE = 0,
|
||||||
|
WIIUSE_EVENT,
|
||||||
|
WIIUSE_STATUS,
|
||||||
|
WIIUSE_CONNECT,
|
||||||
|
WIIUSE_DISCONNECT,
|
||||||
|
WIIUSE_UNEXPECTED_DISCONNECT,
|
||||||
|
WIIUSE_READ_DATA,
|
||||||
|
WIIUSE_NUNCHUK_INSERTED,
|
||||||
|
WIIUSE_NUNCHUK_REMOVED,
|
||||||
|
WIIUSE_CLASSIC_CTRL_INSERTED,
|
||||||
|
WIIUSE_CLASSIC_CTRL_REMOVED,
|
||||||
|
WIIUSE_GUITAR_HERO_3_CTRL_INSERTED,
|
||||||
|
WIIUSE_GUITAR_HERO_3_CTRL_REMOVED
|
||||||
|
} WIIUSE_EVENT_TYPE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct wiimote_t
|
||||||
|
* @brief Wiimote structure.
|
||||||
|
*/
|
||||||
|
typedef struct wiimote_t {
|
||||||
|
WCONST int unid; /**< user specified id */
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
WCONST bdaddr_t bdaddr; /**< bt address */
|
||||||
|
WCONST char bdaddr_str[18]; /**< readable bt address */
|
||||||
|
WCONST int out_sock; /**< output socket */
|
||||||
|
WCONST int in_sock; /**< input socket */
|
||||||
|
#else
|
||||||
|
WCONST HANDLE dev_handle; /**< HID handle */
|
||||||
|
WCONST OVERLAPPED hid_overlap; /**< overlap handle */
|
||||||
|
WCONST enum win_bt_stack_t stack; /**< type of bluetooth stack to use */
|
||||||
|
WCONST int timeout; /**< read timeout */
|
||||||
|
WCONST byte normal_timeout; /**< normal timeout */
|
||||||
|
WCONST byte exp_timeout; /**< timeout for expansion handshake */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WCONST int state; /**< various state flags */
|
||||||
|
WCONST byte leds; /**< currently lit leds */
|
||||||
|
WCONST float battery_level; /**< battery level */
|
||||||
|
|
||||||
|
WCONST int flags; /**< options flag */
|
||||||
|
|
||||||
|
WCONST byte handshake_state; /**< the state of the connection handshake */
|
||||||
|
|
||||||
|
WCONST struct read_req_t* read_req; /**< list of data read requests */
|
||||||
|
WCONST struct accel_t accel_calib; /**< wiimote accelerometer calibration */
|
||||||
|
WCONST struct expansion_t exp; /**< wiimote expansion device */
|
||||||
|
|
||||||
|
WCONST struct vec3b_t accel; /**< current raw acceleration data */
|
||||||
|
WCONST struct orient_t orient; /**< current orientation on each axis */
|
||||||
|
WCONST struct gforce_t gforce; /**< current gravity forces on each axis */
|
||||||
|
|
||||||
|
WCONST struct ir_t ir; /**< IR data */
|
||||||
|
|
||||||
|
WCONST unsigned short btns; /**< what buttons have just been pressed */
|
||||||
|
WCONST unsigned short btns_held; /**< what buttons are being held down */
|
||||||
|
WCONST unsigned short btns_released; /**< what buttons were just released this */
|
||||||
|
|
||||||
|
WCONST float orient_threshold; /**< threshold for orient to generate an event */
|
||||||
|
WCONST int accel_threshold; /**< threshold for accel to generate an event */
|
||||||
|
|
||||||
|
WCONST struct wiimote_state_t lstate; /**< last saved state */
|
||||||
|
|
||||||
|
WCONST WIIUSE_EVENT_TYPE event; /**< type of event that occured */
|
||||||
|
WCONST byte event_buf[MAX_PAYLOAD]; /**< event buffer */
|
||||||
|
} wiimote;
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************
|
||||||
|
*
|
||||||
|
* Include API specific stuff
|
||||||
|
*
|
||||||
|
*****************************************/
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define WIIUSE_EXPORT_DECL __declspec(dllexport)
|
||||||
|
#define WIIUSE_IMPORT_DECL __declspec(dllimport)
|
||||||
|
#else
|
||||||
|
#define WIIUSE_EXPORT_DECL
|
||||||
|
#define WIIUSE_IMPORT_DECL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIIUSE_COMPILE_LIB
|
||||||
|
#define WIIUSE_EXPORT WIIUSE_EXPORT_DECL
|
||||||
|
#else
|
||||||
|
#define WIIUSE_EXPORT WIIUSE_IMPORT_DECL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* wiiuse.c */
|
||||||
|
WIIUSE_EXPORT extern const char* wiiuse_version();
|
||||||
|
|
||||||
|
WIIUSE_EXPORT extern struct wiimote_t** wiiuse_init(int wiimotes);
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_disconnected(struct wiimote_t* wm);
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes);
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_rumble(struct wiimote_t* wm, int status);
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_toggle_rumble(struct wiimote_t* wm);
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_set_leds(struct wiimote_t* wm, int leds);
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_motion_sensing(struct wiimote_t* wm, int status);
|
||||||
|
WIIUSE_EXPORT extern int wiiuse_read_data(struct wiimote_t* wm, byte* buffer, unsigned int offset, unsigned short len);
|
||||||
|
WIIUSE_EXPORT extern int wiiuse_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len);
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_status(struct wiimote_t* wm);
|
||||||
|
WIIUSE_EXPORT extern struct wiimote_t* wiiuse_get_by_id(struct wiimote_t** wm, int wiimotes, int unid);
|
||||||
|
WIIUSE_EXPORT extern int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable);
|
||||||
|
WIIUSE_EXPORT extern float wiiuse_set_smooth_alpha(struct wiimote_t* wm, float alpha);
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_set_bluetooth_stack(struct wiimote_t** wm, int wiimotes, enum win_bt_stack_t type);
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_set_orient_threshold(struct wiimote_t* wm, float threshold);
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_resync(struct wiimote_t* wm);
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, byte normal_timeout, byte exp_timeout);
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_set_accel_threshold(struct wiimote_t* wm, int threshold);
|
||||||
|
|
||||||
|
/* connect.c */
|
||||||
|
WIIUSE_EXPORT extern int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout);
|
||||||
|
WIIUSE_EXPORT extern int wiiuse_connect(struct wiimote_t** wm, int wiimotes);
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_disconnect(struct wiimote_t* wm);
|
||||||
|
|
||||||
|
/* events.c */
|
||||||
|
WIIUSE_EXPORT extern int wiiuse_poll(struct wiimote_t** wm, int wiimotes);
|
||||||
|
|
||||||
|
/* ir.c */
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_set_ir(struct wiimote_t* wm, int status);
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y);
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos);
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect);
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level);
|
||||||
|
|
||||||
|
/* nunchuk.c */
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_set_nunchuk_orient_threshold(struct wiimote_t* wm, float threshold);
|
||||||
|
WIIUSE_EXPORT extern void wiiuse_set_nunchuk_accel_threshold(struct wiimote_t* wm, int threshold);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* WIIUSE_H_INCLUDED */
|
||||||
|
|
||||||
226
src/wiiuse_internal.h
Normal file
226
src/wiiuse_internal.h
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
/*
|
||||||
|
* wiiuse
|
||||||
|
*
|
||||||
|
* Written By:
|
||||||
|
* Michael Laforest < para >
|
||||||
|
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||||
|
*
|
||||||
|
* Copyright 2006-2007
|
||||||
|
*
|
||||||
|
* This file is part of wiiuse.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* $Header$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief General internal wiiuse stuff.
|
||||||
|
*
|
||||||
|
* Since Wiiuse is a library, wiiuse.h is a duplicate
|
||||||
|
* of the API header.
|
||||||
|
*
|
||||||
|
* The code that would normally go in that file, but
|
||||||
|
* which is not needed by third party developers,
|
||||||
|
* is put here.
|
||||||
|
*
|
||||||
|
* So wiiuse_internal.h is included by other files
|
||||||
|
* internally, wiiuse.h is included only here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WIIUSE_INTERNAL_H_INCLUDED
|
||||||
|
#define WIIUSE_INTERNAL_H_INCLUDED
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <arpa/inet.h> /* htons() */
|
||||||
|
#include <bluetooth/bluetooth.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "definitions.h"
|
||||||
|
|
||||||
|
/* wiiuse version */
|
||||||
|
#define WIIUSE_VERSION "0.12"
|
||||||
|
|
||||||
|
/********************
|
||||||
|
*
|
||||||
|
* Wiimote internal codes
|
||||||
|
*
|
||||||
|
********************/
|
||||||
|
|
||||||
|
/* Communication channels */
|
||||||
|
#define WM_OUTPUT_CHANNEL 0x11
|
||||||
|
#define WM_INPUT_CHANNEL 0x13
|
||||||
|
|
||||||
|
#define WM_SET_REPORT 0x50
|
||||||
|
|
||||||
|
/* commands */
|
||||||
|
#define WM_CMD_LED 0x11
|
||||||
|
#define WM_CMD_REPORT_TYPE 0x12
|
||||||
|
#define WM_CMD_RUMBLE 0x13
|
||||||
|
#define WM_CMD_IR 0x13
|
||||||
|
#define WM_CMD_CTRL_STATUS 0x15
|
||||||
|
#define WM_CMD_WRITE_DATA 0x16
|
||||||
|
#define WM_CMD_READ_DATA 0x17
|
||||||
|
#define WM_CMD_IR_2 0x1A
|
||||||
|
|
||||||
|
/* input report ids */
|
||||||
|
#define WM_RPT_CTRL_STATUS 0x20
|
||||||
|
#define WM_RPT_READ 0x21
|
||||||
|
#define WM_RPT_WRITE 0x22
|
||||||
|
#define WM_RPT_BTN 0x30
|
||||||
|
#define WM_RPT_BTN_ACC 0x31
|
||||||
|
#define WM_RPT_BTN_ACC_IR 0x33
|
||||||
|
#define WM_RPT_BTN_EXP 0x34
|
||||||
|
#define WM_RPT_BTN_ACC_EXP 0x35
|
||||||
|
#define WM_RPT_BTN_IR_EXP 0x36
|
||||||
|
#define WM_RPT_BTN_ACC_IR_EXP 0x37
|
||||||
|
|
||||||
|
#define WM_BT_INPUT 0x01
|
||||||
|
#define WM_BT_OUTPUT 0x02
|
||||||
|
|
||||||
|
/* Identify the wiimote device by its class */
|
||||||
|
#define WM_DEV_CLASS_0 0x04
|
||||||
|
#define WM_DEV_CLASS_1 0x25
|
||||||
|
#define WM_DEV_CLASS_2 0x00
|
||||||
|
#define WM_VENDOR_ID 0x057E
|
||||||
|
#define WM_PRODUCT_ID 0x0306
|
||||||
|
|
||||||
|
/* controller status stuff */
|
||||||
|
#define WM_MAX_BATTERY_CODE 0xC8
|
||||||
|
|
||||||
|
/* offsets in wiimote memory */
|
||||||
|
#define WM_MEM_OFFSET_CALIBRATION 0x16
|
||||||
|
#define WM_EXP_MEM_BASE 0x04A40000
|
||||||
|
#define WM_EXP_MEM_ENABLE 0x04A40040
|
||||||
|
#define WM_EXP_MEM_CALIBR 0x04A40020
|
||||||
|
|
||||||
|
#define WM_REG_IR 0x04B00030
|
||||||
|
#define WM_REG_IR_BLOCK1 0x04B00000
|
||||||
|
#define WM_REG_IR_BLOCK2 0x04B0001A
|
||||||
|
#define WM_REG_IR_MODENUM 0x04B00033
|
||||||
|
|
||||||
|
/* ir block data */
|
||||||
|
#define WM_IR_BLOCK1_LEVEL1 "\x02\x00\x00\x71\x01\x00\x64\x00\xfe"
|
||||||
|
#define WM_IR_BLOCK2_LEVEL1 "\xfd\x05"
|
||||||
|
#define WM_IR_BLOCK1_LEVEL2 "\x02\x00\x00\x71\x01\x00\x96\x00\xb4"
|
||||||
|
#define WM_IR_BLOCK2_LEVEL2 "\xb3\x04"
|
||||||
|
#define WM_IR_BLOCK1_LEVEL3 "\x02\x00\x00\x71\x01\x00\xaa\x00\x64"
|
||||||
|
#define WM_IR_BLOCK2_LEVEL3 "\x63\x03"
|
||||||
|
#define WM_IR_BLOCK1_LEVEL4 "\x02\x00\x00\x71\x01\x00\xc8\x00\x36"
|
||||||
|
#define WM_IR_BLOCK2_LEVEL4 "\x35\x03"
|
||||||
|
#define WM_IR_BLOCK1_LEVEL5 "\x07\x00\x00\x71\x01\x00\x72\x00\x20"
|
||||||
|
#define WM_IR_BLOCK2_LEVEL5 "\x1f\x03"
|
||||||
|
|
||||||
|
#define WM_IR_TYPE_BASIC 0x01
|
||||||
|
#define WM_IR_TYPE_EXTENDED 0x03
|
||||||
|
|
||||||
|
/* controller status flags for the first message byte */
|
||||||
|
/* bit 1 is unknown */
|
||||||
|
#define WM_CTRL_STATUS_BYTE1_ATTACHMENT 0x02
|
||||||
|
#define WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED 0x04
|
||||||
|
#define WM_CTRL_STATUS_BYTE1_IR_ENABLED 0x08
|
||||||
|
#define WM_CTRL_STATUS_BYTE1_LED_1 0x10
|
||||||
|
#define WM_CTRL_STATUS_BYTE1_LED_2 0x20
|
||||||
|
#define WM_CTRL_STATUS_BYTE1_LED_3 0x40
|
||||||
|
#define WM_CTRL_STATUS_BYTE1_LED_4 0x80
|
||||||
|
|
||||||
|
/* aspect ratio */
|
||||||
|
#define WM_ASPECT_16_9_X 660
|
||||||
|
#define WM_ASPECT_16_9_Y 370
|
||||||
|
#define WM_ASPECT_4_3_X 560
|
||||||
|
#define WM_ASPECT_4_3_Y 420
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expansion stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* encrypted expansion id codes (located at 0x04A400FC) */
|
||||||
|
#define EXP_ID_CODE_NUNCHUK 0x9A1EFEFE
|
||||||
|
#define EXP_ID_CODE_CLASSIC_CONTROLLER 0x9A1EFDFD
|
||||||
|
#define EXP_ID_CODE_GUITAR 0x9A1EFDFB
|
||||||
|
|
||||||
|
#define EXP_HANDSHAKE_LEN 224
|
||||||
|
|
||||||
|
/********************
|
||||||
|
*
|
||||||
|
* End Wiimote internal codes
|
||||||
|
*
|
||||||
|
********************/
|
||||||
|
|
||||||
|
/* wiimote state flags - (some duplicated in wiiuse.h)*/
|
||||||
|
#define WIIMOTE_STATE_DEV_FOUND 0x0001
|
||||||
|
#define WIIMOTE_STATE_HANDSHAKE 0x0002 /* actual connection exists but no handshake yet */
|
||||||
|
#define WIIMOTE_STATE_HANDSHAKE_COMPLETE 0x0004 /* actual connection exists but no handshake yet */
|
||||||
|
#define WIIMOTE_STATE_CONNECTED 0x0008
|
||||||
|
#define WIIMOTE_STATE_RUMBLE 0x0010
|
||||||
|
#define WIIMOTE_STATE_ACC 0x0020
|
||||||
|
#define WIIMOTE_STATE_EXP 0x0040
|
||||||
|
#define WIIMOTE_STATE_IR 0x0080
|
||||||
|
#define WIIMOTE_STATE_SPEAKER 0x0100
|
||||||
|
#define WIIMOTE_STATE_IR_SENS_LVL1 0x0200
|
||||||
|
#define WIIMOTE_STATE_IR_SENS_LVL2 0x0400
|
||||||
|
#define WIIMOTE_STATE_IR_SENS_LVL3 0x0800
|
||||||
|
#define WIIMOTE_STATE_IR_SENS_LVL4 0x1000
|
||||||
|
#define WIIMOTE_STATE_IR_SENS_LVL5 0x2000
|
||||||
|
|
||||||
|
#define WIIMOTE_INIT_STATES (WIIMOTE_STATE_IR_SENS_LVL3)
|
||||||
|
|
||||||
|
/* macro to manage states */
|
||||||
|
#define WIIMOTE_IS_SET(wm, s) ((wm->state & (s)) == (s))
|
||||||
|
#define WIIMOTE_ENABLE_STATE(wm, s) (wm->state |= (s))
|
||||||
|
#define WIIMOTE_DISABLE_STATE(wm, s) (wm->state &= ~(s))
|
||||||
|
#define WIIMOTE_TOGGLE_STATE(wm, s) ((wm->state & (s)) ? WIIMOTE_DISABLE_STATE(wm, s) : WIIMOTE_ENABLE_STATE(wm, s))
|
||||||
|
|
||||||
|
#define WIIMOTE_IS_FLAG_SET(wm, s) ((wm->flags & (s)) == (s))
|
||||||
|
#define WIIMOTE_ENABLE_FLAG(wm, s) (wm->flags |= (s))
|
||||||
|
#define WIIMOTE_DISABLE_FLAG(wm, s) (wm->flags &= ~(s))
|
||||||
|
#define WIIMOTE_TOGGLE_FLAG(wm, s) ((wm->flags & (s)) ? WIIMOTE_DISABLE_FLAG(wm, s) : WIIMOTE_ENABLE_FLAG(wm, s))
|
||||||
|
|
||||||
|
#define NUNCHUK_IS_FLAG_SET(wm, s) ((*(wm->flags) & (s)) == (s))
|
||||||
|
|
||||||
|
/* misc macros */
|
||||||
|
#define WIIMOTE_ID(wm) (wm->unid)
|
||||||
|
#define WIIMOTE_IS_CONNECTED(wm) (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_CONNECTED))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Smooth tilt calculations are computed with the
|
||||||
|
* exponential moving average formula:
|
||||||
|
* St = St_last + (alpha * (tilt - St_last))
|
||||||
|
* alpha is between 0 and 1
|
||||||
|
*/
|
||||||
|
#define WIIUSE_DEFAULT_SMOOTH_ALPHA 0.07f
|
||||||
|
|
||||||
|
#define SMOOTH_ROLL 0x01
|
||||||
|
#define SMOOTH_PITCH 0x02
|
||||||
|
|
||||||
|
#include "wiiuse.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* not part of the api */
|
||||||
|
int wiiuse_set_report_type(struct wiimote_t* wm);
|
||||||
|
void wiiuse_send_next_pending_read_request(struct wiimote_t* wm);
|
||||||
|
int wiiuse_send(struct wiimote_t* wm, byte report_type, byte* msg, int len);
|
||||||
|
int wiiuse_read_data_cb(struct wiimote_t* wm, wiiuse_read_cb read_cb, byte* buffer, unsigned int offset, unsigned short len);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* WIIUSE_INTERNAL_H_INCLUDED */
|
||||||
86
wiiuse.cbp
Normal file
86
wiiuse.cbp
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||||
|
<CodeBlocks_project_file>
|
||||||
|
<FileVersion major="1" minor="6" />
|
||||||
|
<Project>
|
||||||
|
<Option title="wiiuse" />
|
||||||
|
<Option makefile_is_custom="1" />
|
||||||
|
<Option pch_mode="2" />
|
||||||
|
<Option compiler="gcc" />
|
||||||
|
<MakeCommands>
|
||||||
|
<Build command="$make $target" />
|
||||||
|
<CompileFile command="$make $file" />
|
||||||
|
<Clean command="$make clean" />
|
||||||
|
<DistClean command="$make distclean" />
|
||||||
|
</MakeCommands>
|
||||||
|
<Build>
|
||||||
|
<Target title="Release">
|
||||||
|
<Option output="bin/Release/wiiuse" prefix_auto="1" extension_auto="1" />
|
||||||
|
<Option object_output="obj/Release/" />
|
||||||
|
<Option type="1" />
|
||||||
|
<Option compiler="gcc" />
|
||||||
|
<Compiler>
|
||||||
|
<Add option="-O2" />
|
||||||
|
</Compiler>
|
||||||
|
<Linker>
|
||||||
|
<Add option="-s" />
|
||||||
|
</Linker>
|
||||||
|
</Target>
|
||||||
|
</Build>
|
||||||
|
<Compiler>
|
||||||
|
<Add option="-Wall" />
|
||||||
|
</Compiler>
|
||||||
|
<Unit filename="CHANGELOG" />
|
||||||
|
<Unit filename="README" />
|
||||||
|
<Unit filename="example-sdl/sdl.c">
|
||||||
|
<Option compilerVar="CC" />
|
||||||
|
</Unit>
|
||||||
|
<Unit filename="example/example.c">
|
||||||
|
<Option compilerVar="CC" />
|
||||||
|
</Unit>
|
||||||
|
<Unit filename="src/classic.c">
|
||||||
|
<Option compilerVar="CC" />
|
||||||
|
</Unit>
|
||||||
|
<Unit filename="src/classic.h" />
|
||||||
|
<Unit filename="src/definitions.h" />
|
||||||
|
<Unit filename="src/dynamics.c">
|
||||||
|
<Option compilerVar="CC" />
|
||||||
|
</Unit>
|
||||||
|
<Unit filename="src/dynamics.h" />
|
||||||
|
<Unit filename="src/events.c">
|
||||||
|
<Option compilerVar="CC" />
|
||||||
|
</Unit>
|
||||||
|
<Unit filename="src/events.h" />
|
||||||
|
<Unit filename="src/guitar_hero_3.c">
|
||||||
|
<Option compilerVar="CC" />
|
||||||
|
</Unit>
|
||||||
|
<Unit filename="src/guitar_hero_3.h" />
|
||||||
|
<Unit filename="src/io.c">
|
||||||
|
<Option compilerVar="CC" />
|
||||||
|
</Unit>
|
||||||
|
<Unit filename="src/io.h" />
|
||||||
|
<Unit filename="src/io_nix.c">
|
||||||
|
<Option compilerVar="CC" />
|
||||||
|
</Unit>
|
||||||
|
<Unit filename="src/io_win.c">
|
||||||
|
<Option compilerVar="CC" />
|
||||||
|
</Unit>
|
||||||
|
<Unit filename="src/ir.c">
|
||||||
|
<Option compilerVar="CC" />
|
||||||
|
</Unit>
|
||||||
|
<Unit filename="src/ir.h" />
|
||||||
|
<Unit filename="src/nunchuk.c">
|
||||||
|
<Option compilerVar="CC" />
|
||||||
|
</Unit>
|
||||||
|
<Unit filename="src/nunchuk.h" />
|
||||||
|
<Unit filename="src/os.h" />
|
||||||
|
<Unit filename="src/wiiuse.c">
|
||||||
|
<Option compilerVar="CC" />
|
||||||
|
</Unit>
|
||||||
|
<Unit filename="src/wiiuse.h" />
|
||||||
|
<Unit filename="src/wiiuse_internal.h" />
|
||||||
|
<Extensions>
|
||||||
|
<code_completion />
|
||||||
|
<debugger />
|
||||||
|
</Extensions>
|
||||||
|
</Project>
|
||||||
|
</CodeBlocks_project_file>
|
||||||
61
wiiuse.layout
Normal file
61
wiiuse.layout
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||||
|
<CodeBlocks_layout_file>
|
||||||
|
<ActiveTarget name="Release" />
|
||||||
|
<File name="CHANGELOG" open="1" top="0" tabpos="7">
|
||||||
|
<Cursor position="0" topLine="0" />
|
||||||
|
</File>
|
||||||
|
<File name="README" open="0" top="0" tabpos="8">
|
||||||
|
<Cursor position="3582" topLine="0" />
|
||||||
|
</File>
|
||||||
|
<File name="example-sdl/sdl.c" open="1" top="0" tabpos="6">
|
||||||
|
<Cursor position="3235" topLine="105" />
|
||||||
|
</File>
|
||||||
|
<File name="example/example.c" open="1" top="0" tabpos="5">
|
||||||
|
<Cursor position="0" topLine="0" />
|
||||||
|
</File>
|
||||||
|
<File name="src/classic.c" open="0" top="0" tabpos="4">
|
||||||
|
<Cursor position="2464" topLine="53" />
|
||||||
|
</File>
|
||||||
|
<File name="src/definitions.h" open="1" top="0" tabpos="9">
|
||||||
|
<Cursor position="1099" topLine="12" />
|
||||||
|
</File>
|
||||||
|
<File name="src/dynamics.c" open="0" top="0" tabpos="10">
|
||||||
|
<Cursor position="3216" topLine="59" />
|
||||||
|
</File>
|
||||||
|
<File name="src/events.c" open="1" top="0" tabpos="4">
|
||||||
|
<Cursor position="2983" topLine="117" />
|
||||||
|
</File>
|
||||||
|
<File name="src/guitar_hero_3.c" open="0" top="0" tabpos="0">
|
||||||
|
<Cursor position="2604" topLine="45" />
|
||||||
|
</File>
|
||||||
|
<File name="src/io.c" open="0" top="0" tabpos="6">
|
||||||
|
<Cursor position="1817" topLine="60" />
|
||||||
|
</File>
|
||||||
|
<File name="src/io_nix.c" open="0" top="0" tabpos="8">
|
||||||
|
<Cursor position="6286" topLine="211" />
|
||||||
|
</File>
|
||||||
|
<File name="src/io_win.c" open="0" top="0" tabpos="9">
|
||||||
|
<Cursor position="4021" topLine="123" />
|
||||||
|
</File>
|
||||||
|
<File name="src/ir.c" open="1" top="0" tabpos="8">
|
||||||
|
<Cursor position="0" topLine="0" />
|
||||||
|
</File>
|
||||||
|
<File name="src/ir.h" open="0" top="0" tabpos="0">
|
||||||
|
<Cursor position="1059" topLine="0" />
|
||||||
|
</File>
|
||||||
|
<File name="src/nunchuk.c" open="0" top="0" tabpos="10">
|
||||||
|
<Cursor position="2454" topLine="43" />
|
||||||
|
</File>
|
||||||
|
<File name="src/nunchuk.h" open="0" top="0" tabpos="0">
|
||||||
|
<Cursor position="1171" topLine="0" />
|
||||||
|
</File>
|
||||||
|
<File name="src/wiiuse.c" open="1" top="0" tabpos="1">
|
||||||
|
<Cursor position="0" topLine="0" />
|
||||||
|
</File>
|
||||||
|
<File name="src/wiiuse.h" open="1" top="1" tabpos="2">
|
||||||
|
<Cursor position="0" topLine="0" />
|
||||||
|
</File>
|
||||||
|
<File name="src/wiiuse_internal.h" open="1" top="0" tabpos="3">
|
||||||
|
<Cursor position="3424" topLine="81" />
|
||||||
|
</File>
|
||||||
|
</CodeBlocks_layout_file>
|
||||||
Reference in New Issue
Block a user