├── .gitignore.txt
├── Info.plist
├── LICENSE
├── QJoyControl.pro
├── README.md
├── eventhandler.h
├── hidapi
├── .appveyor.yml
├── .builds
│ ├── alpine.yml
│ ├── archlinux.yml
│ ├── fedora-mingw.yml
│ └── freebsd.yml
├── .gitattributes
├── .gitignore
├── .travis.yml
├── AUTHORS.txt
├── HACKING.txt
├── LICENSE-bsd.txt
├── LICENSE-gpl3.txt
├── LICENSE-orig.txt
├── LICENSE.txt
├── Makefile.am
├── README.md
├── android
│ └── jni
│ │ └── Android.mk
├── bootstrap
├── configure.ac
├── dist
│ └── hidapi.podspec
├── doxygen
│ └── Doxyfile
├── hidapi
│ └── hidapi.h
├── hidtest
│ ├── .gitignore
│ ├── Makefile.am
│ └── test.c
├── libusb
│ ├── .gitignore
│ ├── Makefile-manual
│ ├── Makefile.am
│ ├── Makefile.freebsd
│ ├── Makefile.linux
│ └── hid.c
├── linux
│ ├── .gitignore
│ ├── Makefile-manual
│ ├── Makefile.am
│ └── hid.c
├── m4
│ ├── .gitignore
│ ├── ax_pthread.m4
│ └── pkg.m4
├── mac
│ ├── .gitignore
│ ├── Makefile-manual
│ ├── Makefile.am
│ ├── hid.c
│ └── hidtest
├── pc
│ ├── .gitignore
│ ├── hidapi-hidraw.pc.in
│ ├── hidapi-libusb.pc.in
│ └── hidapi.pc.in
├── testgui
│ ├── .gitignore
│ ├── Makefile-manual
│ ├── Makefile.am
│ ├── Makefile.freebsd
│ ├── Makefile.linux
│ ├── Makefile.mac
│ ├── Makefile.mingw
│ ├── TestGUI.app.in
│ │ └── Contents
│ │ │ ├── Info.plist
│ │ │ ├── PkgInfo
│ │ │ └── Resources
│ │ │ ├── English.lproj
│ │ │ └── InfoPlist.strings
│ │ │ └── Signal11.icns
│ ├── copy_to_bundle.sh
│ ├── mac_support.h
│ ├── mac_support_cocoa.m
│ ├── test.cpp
│ ├── testgui.sln
│ └── testgui.vcproj
├── udev
│ └── 99-hid.rules
└── windows
│ ├── .gitignore
│ ├── Makefile-manual
│ ├── Makefile.am
│ ├── Makefile.mingw
│ ├── ddk_build
│ ├── .gitignore
│ ├── hidapi.def
│ └── sources
│ ├── hid.c
│ ├── hidapi.sln
│ ├── hidapi.vcproj
│ ├── hidapi.vcxproj
│ ├── hidtest.vcproj
│ └── hidtest.vcxproj
├── img
├── Logo.icns
├── Logo.png
├── Logo.svg
├── batt_0.png
├── batt_0_chr.png
├── batt_100.png
├── batt_100_chr.png
├── batt_25.png
├── batt_25_chr.png
├── batt_50.png
├── batt_50_chr.png
├── batt_75.png
├── batt_75_chr.png
└── retail_colors.xml
├── inputmappanel.cpp
├── inputmappanel.h
├── inputmappanel.ui
├── inputmapwidget.cpp
├── inputmapwidget.h
├── inputmapwidget.ui
├── ir_sensor.h
├── joyconworker.cpp
├── joyconworker.h
├── linux
├── .gitignore
└── eventhandler_linux.cpp
├── luts.h
├── mac
├── .gitignore
├── eventhandler_macos.cpp
├── powertools.h
└── powertools.mm
├── main.cpp
├── mainwindow.cpp
├── mainwindow.h
├── mainwindow.ui
├── resources.qrc
├── statuswidget.cpp
├── statuswidget.h
└── statuswidget.ui
/.gitignore.txt:
--------------------------------------------------------------------------------
1 | # C++ objects and libs
2 | *.slo
3 | *.lo
4 | *.o
5 | *.a
6 | *.la
7 | *.lai
8 | *.so
9 | *.so.*
10 | *.dll
11 | *.dylib
12 |
13 | # Qt-es
14 | object_script.*.Release
15 | object_script.*.Debug
16 | *_plugin_import.cpp
17 | /.qmake.cache
18 | /.qmake.stash
19 | *.pro.user
20 | *.pro.user.*
21 | *.qbs.user
22 | *.qbs.user.*
23 | *.moc
24 | moc_*.cpp
25 | moc_*.h
26 | qrc_*.cpp
27 | ui_*.h
28 | *.qmlc
29 | *.jsc
30 | Makefile*
31 | *build-*
32 | *.qm
33 | *.prl
34 |
35 | # Qt unit tests
36 | target_wrapper.*
37 |
38 | # QtCreator
39 | *.autosave
40 |
41 | # QtCreator Qml
42 | *.qmlproject.user
43 | *.qmlproject.user.*
44 |
45 | # QtCreator CMake
46 | CMakeLists.txt.user*
47 |
48 | # QtCreator 4.8< compilation database
49 | compile_commands.json
50 |
51 | # QtCreator local machine specific files for imported projects
52 | *creator.user*
--------------------------------------------------------------------------------
/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleExecutable
6 | QJoyControl
7 | CFBundleGetInfoString
8 | Created by Qt/QMake
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | com.yourcompany.QJoyControl
13 | CFBundlePackageType
14 | APPL
15 | CFBundleSignature
16 | ????
17 | LSMinimumSystemVersion
18 | 10.12
19 | LSUIElement
20 | 1
21 | NOTE
22 | This file was generated by Qt/QMake.
23 | NSPrincipalClass
24 | NSApplication
25 | NSSupportsAutomaticGraphicsSwitching
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Erik Werner
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/QJoyControl.pro:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------
2 | #
3 | # Project created by Erik Werner 2018-09-22T21:09:40
4 | #
5 | #-------------------------------------------------
6 |
7 | QT += core gui widgets
8 |
9 | TARGET = QJoyControl
10 | TEMPLATE = app
11 |
12 | VERSION = 0.2
13 | QMAKE_TARGET_PRODUCT = "QJoyControl"
14 | QMAKE_TARGET_COMPANY = "UntitledSoftware"
15 |
16 | DEFINES += APP_VERSION=\"\\\"$${VERSION}\\\"\" \
17 | APP_PRODUCT=\"\\\"$${QMAKE_TARGET_PRODUCT}\\\"\" \
18 | APP_COMPANY=\"\\\"$${QMAKE_TARGET_COMPANY}\\\"\"
19 |
20 |
21 | # With C++11 support
22 | greaterThan(QT_MAJOR_VERSION, 4){
23 | CONFIG += c++11
24 | } else {
25 | QMAKE_CXXFLAGS += -std=c++0x
26 | }
27 |
28 | INCLUDEPATH += hidapi/hidapi
29 |
30 | SOURCES += \
31 | inputmappanel.cpp \
32 | inputmapwidget.cpp \
33 | main.cpp \
34 | mainwindow.cpp \
35 | joyconworker.cpp \
36 | statuswidget.cpp
37 |
38 |
39 |
40 | HEADERS += \
41 | inputmappanel.h \
42 | inputmapwidget.h \
43 | mainwindow.h \
44 | joyconworker.h \
45 | luts.h \
46 | ir_sensor.h \
47 | statuswidget.h \
48 | eventhandler.h \
49 | hidapi/hidapi/hidapi.h
50 |
51 | FORMS += \
52 | inputmappanel.ui \
53 | inputmapwidget.ui \
54 | mainwindow.ui \
55 | statuswidget.ui
56 |
57 | macx {
58 | CONFIG += app_bundle
59 | QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7
60 | ICON = img/Logo.icns
61 |
62 | # use custom plist to hide dock icon
63 | #QMAKE_INFO_PLIST = Info.plist
64 |
65 | # for homebrew hidapi installation
66 | #HIDAPI_PATH = /usr/local/Cellar/hidapi/0.9.0
67 | #INCLUDEPATH += $$HIDAPI_PATH/include/hidapi
68 |
69 | # use local hidapi installation
70 | SOURCES += hidapi/mac/hid.c
71 | HIDAPI_PATH = $$PWD/hidapi/mac
72 | INCLUDEPATH += $$HIDAPI_PATH
73 |
74 | #prevent app nap from sleeping threads
75 | INCLUDEPATH += $$PWD/mac
76 | HEADERS += mac/powertools.h
77 | OBJECTIVE_SOURCES += mac/powertools.mm
78 | LIBS += -framework Foundation
79 |
80 | # include hidapi dynamic library
81 | #LIBS += $$HIDAPI_PATH/lib/libhidapi.dylib
82 |
83 | # include power management libs
84 | LIBS += -framework CoreFoundation -framework IOkit
85 |
86 | # include system event services Mac
87 | LIBS += -framework ApplicationServices
88 | SOURCES += mac/eventhandler_macos.cpp
89 | }
90 |
91 | unix:!macx {
92 | SOURCES += linux/hid-libusb.c
93 | LIBS += -lusb-1.0
94 | # include system event services Linux
95 | #unix: !macx: LIB +=
96 | SOURCES += eventhandler_linux.cpp
97 | }
98 |
99 | win32 {
100 | # include system event services Windows
101 | #win32: LIB +=
102 | SOURCES += eventhandler_win.cpp
103 | SOURCES += windows/hid.cpp
104 | LIBS += -lSetupAPI
105 | }
106 |
107 | RESOURCES += \
108 | resources.qrc
109 |
110 | # Default rules for deployment.
111 | qnx: target.path = /tmp/$${TARGET}/bin
112 | else: unix:!android: target.path = /opt/$${TARGET}/bin
113 | !isEmpty(target.path): INSTALLS += target
114 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # QJoyControl
2 | QJoyControl lets you use Nintendo Switch JoyCons as input devices on your computer. It was originally made to use a JoyCon as a PowerPoint remote, but it accumulated a few extra features along the way. Currently, QJoyControl supports:
3 | * JoyCons and Pro Controller
4 | * Mouse control with analog sticks and gyroscope
5 | * Adjustable mouse sensitivity
6 | * Configurable button-to-key mapping
7 | * Image capture with the IR Camera
8 | * Rumble and player LED commands
9 |
10 | It also works pretty well as a PowerPoint remote.
11 |
12 | ## Setup
13 | 1. Pair the JoyCon with your computer and connect to it with bluetooth
14 | * To pair, press the pairing button on the JoyCon and go to Bluetooth Preferences on your Mac
15 | 2. Open QJoyControl and select the JoyCon from the device list
16 | * If nothing shows up, make sure the JoyCon is paired and connected and click Refresh to check again
17 | 3. Click Connect to begin streaming input data
18 |
19 | If MacOS does not ask to give QJoyControl permission to control your computer, you may need to go into System Preferences and do it manually before keyboard and mouse inputs will register with MacOS. To do this, go to System Preferences, Security & Privacy > Privacy > Accessibility. From there, click the lock icon in the bottom-left corner, enter you password to unlock, click the plus button, and select QJoyControl to add QJoyControl to the list of approved applications.
20 |
21 | ## Compatibility
22 | QJoyControl should work on MacOS 10.7 and later, although it has only been tested on MacOS 10.13 and 10.14. QJoyControl was written with Qt and [hidapi](https://github.com/signal11/hidapi) for cross-platform support. It should eventually work on MacOS, Windows, and Linux, but at the moment only MacOS support is implemented.
23 |
24 | ## Thanks
25 | * All of the HID communication came from the hard work at [JoyCon Reverse Engineering](https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering)
26 | * The IR camera features came from the excellent [Joy-Con Toolkit](https://github.com/CTCaer/jc_toolkit)
27 |
28 | ## Disclaimer
29 | This project is not endorsed by, affiliated with, maintained, authorized, or sponsored by Nintendo. All product and company names are the registered trademarks of their original owners. The use of any trade name or trademark is for identification and reference purposes only and does not imply any association with the trademark holder of their product brand.
30 |
--------------------------------------------------------------------------------
/eventhandler.h:
--------------------------------------------------------------------------------
1 | #ifndef EVENTHANDLER_H
2 | #define EVENTHANDLER_H
3 |
4 | #include
5 | #include
6 |
7 | /*!
8 | * \brief The JOYCON_BUTTONS enum is used to mask
9 | * button status from the bytes of a standard input report
10 | * the joycons
11 | */
12 | enum JOYCON_BUTTONS : int {
13 | // byte 3:
14 | R_BUT_Y = 1,
15 | R_BUT_X = 2,
16 | R_BUT_B = 4,
17 | R_BUT_A = 8,
18 | R_BUT_SR = 16,
19 | R_BUT_SL = 32,
20 | R_BUT_R = 64,
21 | R_BUT_ZR = 128,
22 | // byte 4:, & with 256 for key mapping
23 | L_BUT_MINUS= 1,
24 | R_BUT_PLUS = 2,
25 | R_BUT_STICK = 4,
26 | L_BUT_STICK = 8,
27 | R_BUT_HOME = 16,
28 | L_BUT_CAP = 32,
29 | // 64 is unused
30 | CHARGE_GRIP = 128,
31 | // byte 5:, & with 512 for key mapping
32 | L_BUT_DOWN = 1,
33 | L_BUT_UP = 2,
34 | L_BUT_RIGHT = 4,
35 | L_BUT_LEFT = 8,
36 | L_BUT_SR = 16,
37 | L_BUT_SL = 32,
38 | L_BUT_L = 64,
39 | L_BUT_ZL = 128
40 | };
41 |
42 | class EventHandler
43 | {
44 | public:
45 | EventHandler();
46 | void handleMouseMove(double dx, double dy);
47 | void handleButtonPress(int button_mask);
48 | void handleButtonRelease(int button_mask);
49 | void addMapping(int from, int to);
50 | void mapToMouseButton(int mask, int button);
51 |
52 | private:
53 | //< a map to lookup OS button press from JoyCon buttom press
54 | //< JoyCon buttons from byte 4 are & with 256
55 | //< JoyCon buttons from byte 5 are & with 512
56 | QMap keyCodeMap;
57 | QMap qt_to_cg;
58 | bool _left_button_down = false;
59 | bool _right_button_down = false;
60 | };
61 |
62 | #endif // EVENTHANDLER_H
63 |
--------------------------------------------------------------------------------
/hidapi/.appveyor.yml:
--------------------------------------------------------------------------------
1 | os: Visual Studio 2015
2 |
3 | environment:
4 | matrix:
5 | - BUILD_ENV: msbuild
6 | arch: x64
7 | - BUILD_ENV: msbuild
8 | arch: Win32
9 | - BUILD_ENV: cygwin
10 |
11 | install:
12 | - cmd: if %BUILD_ENV%==cygwin (
13 | C:\cygwin64\setup-x86_64.exe --quiet-mode --no-shortcuts --upgrade-also --packages autoconf,automake )
14 |
15 | build_script:
16 | - cmd: if %BUILD_ENV%==msbuild (
17 | msbuild .\windows\hidapi.sln /p:Configuration=Release /p:Platform=%arch% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" )
18 | - cmd: if %BUILD_ENV%==cygwin (
19 | C:\cygwin64\bin\bash -exlc "cd $APPVEYOR_BUILD_FOLDER; ./bootstrap; ./configure; make" )
20 |
21 | artifacts:
22 | # Win32 artifacts
23 | - path: .\windows\Release\hidapi.dll
24 | - path: .\windows\Release\hidapi.lib
25 | - path: .\windows\Release\hidapi.pdb
26 | - path: .\windows\Release\hidtest.exe
27 | - path: .\windows\Release\hidtest.pdb
28 | # x64 artifacts
29 | - path: .\windows\x64\Release\hidapi.dll
30 | - path: .\windows\x64\Release\hidapi.lib
31 | - path: .\windows\x64\Release\hidapi.pdb
32 | - path: .\windows\x64\Release\hidtest.exe
33 | - path: .\windows\x64\Release\hidtest.pdb
34 |
--------------------------------------------------------------------------------
/hidapi/.builds/alpine.yml:
--------------------------------------------------------------------------------
1 | image: alpine/edge
2 | packages:
3 | - autoconf
4 | - automake
5 | - libtool
6 | - eudev-dev
7 | - libusb-dev
8 | - linux-headers
9 | sources:
10 | - https://github.com/libusb/hidapi
11 | tasks:
12 | - setup: |
13 | cd hidapi
14 | ./bootstrap
15 | ./configure
16 | - build: |
17 | cd hidapi
18 | make
19 | make DESTDIR=$PWD/root install
20 |
--------------------------------------------------------------------------------
/hidapi/.builds/archlinux.yml:
--------------------------------------------------------------------------------
1 | image: archlinux
2 | sources:
3 | - https://github.com/libusb/hidapi
4 | tasks:
5 | - setup: |
6 | cd hidapi
7 | ./bootstrap
8 | ./configure
9 | - build: |
10 | cd hidapi
11 | make
12 | make DESTDIR=$PWD/root install
13 |
--------------------------------------------------------------------------------
/hidapi/.builds/fedora-mingw.yml:
--------------------------------------------------------------------------------
1 | image: fedora/latest
2 | packages:
3 | - autoconf
4 | - automake
5 | - libtool
6 | - mingw64-gcc
7 | - mingw64-gcc-c++
8 | sources:
9 | - https://github.com/libusb/hidapi
10 | tasks:
11 | - setup: |
12 | cd hidapi
13 | ./bootstrap
14 | mingw64-configure
15 | - build: |
16 | cd hidapi
17 | make
18 | make DESTDIR=$PWD/root install
19 |
--------------------------------------------------------------------------------
/hidapi/.builds/freebsd.yml:
--------------------------------------------------------------------------------
1 | image: freebsd/latest
2 | packages:
3 | - autoconf
4 | - automake
5 | - libiconv
6 | - libtool
7 | - pkgconf
8 | sources:
9 | - https://github.com/libusb/hidapi
10 | tasks:
11 | - setup: |
12 | cd hidapi
13 | ./bootstrap
14 | ./configure
15 | - build: |
16 | cd hidapi
17 | make
18 | make DESTDIR=$PWD/root install
19 |
--------------------------------------------------------------------------------
/hidapi/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 |
3 | *.sln text eol=crlf
4 | *.vcproj text eol=crlf
5 |
6 | bootstrap text eol=lf
7 | configure.ac text eol=lf
8 |
--------------------------------------------------------------------------------
/hidapi/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Autotools-added generated files
3 | Makefile.in
4 | aclocal.m4
5 | ar-lib
6 | autom4te.cache/
7 | config.*
8 | configure
9 | compile
10 | depcomp
11 | install-sh
12 | libusb/Makefile.in
13 | linux/Makefile.in
14 | ltmain.sh
15 | mac/Makefile.in
16 | missing
17 | testgui/Makefile.in
18 | windows/Makefile.in
19 |
20 | Makefile
21 | stamp-h1
22 | libtool
23 |
--------------------------------------------------------------------------------
/hidapi/.travis.yml:
--------------------------------------------------------------------------------
1 | language: c
2 |
3 | os: osx
4 | osx_image: xcode10.2
5 |
6 | script:
7 | - ./bootstrap
8 | - ./configure
9 | - make
10 | - make DESTDIR=$PWD/root install
11 |
--------------------------------------------------------------------------------
/hidapi/AUTHORS.txt:
--------------------------------------------------------------------------------
1 |
2 | HIDAPI Authors:
3 |
4 | Alan Ott :
5 | Original Author and Maintainer
6 | Linux, Windows, and Mac implementations
7 |
8 | Ludovic Rousseau :
9 | Formatting for Doxygen documentation
10 | Bug fixes
11 | Correctness fixes
12 |
13 | libusb/hidapi Team:
14 | Development/maintainance since June 4th 2019
15 |
16 | For a comprehensive list of contributions, see the commit list at github:
17 | https://github.com/libusb/hidapi/commits/master
18 |
19 |
--------------------------------------------------------------------------------
/hidapi/HACKING.txt:
--------------------------------------------------------------------------------
1 | This file is mostly for the maintainer.
2 |
3 | 1. Build hidapi.dll
4 | 2. Build hidtest.exe in DEBUG and RELEASE
5 | 3. Commit all
6 |
7 | 4. Run the Following
8 | export VERSION=0.1.0
9 | export TAG_NAME=hidapi-$VERSION
10 | git tag $TAG_NAME
11 | git archive --format zip --prefix $TAG_NAME/ $TAG_NAME >../$TAG_NAME.zip
12 | 5. Test the zip file.
13 | 6. Run the following:
14 | git push origin $TAG_NAME
15 |
16 |
--------------------------------------------------------------------------------
/hidapi/LICENSE-bsd.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010, Alan Ott, Signal 11 Software
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice,
8 | this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | * Neither the name of Signal 11 Software nor the names of its
13 | contributors may be used to endorse or promote products derived from
14 | this software without specific prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 | POSSIBILITY OF SUCH DAMAGE.
27 |
--------------------------------------------------------------------------------
/hidapi/LICENSE-orig.txt:
--------------------------------------------------------------------------------
1 | HIDAPI - Multi-Platform library for
2 | communication with HID devices.
3 |
4 | Copyright 2009, Alan Ott, Signal 11 Software.
5 | All Rights Reserved.
6 |
7 | This software may be used by anyone for any reason so
8 | long as the copyright notice in the source files
9 | remains intact.
10 |
--------------------------------------------------------------------------------
/hidapi/LICENSE.txt:
--------------------------------------------------------------------------------
1 | HIDAPI can be used under one of three licenses.
2 |
3 | 1. The GNU General Public License, version 3.0, in LICENSE-gpl3.txt
4 | 2. A BSD-Style License, in LICENSE-bsd.txt.
5 | 3. The more liberal original HIDAPI license. LICENSE-orig.txt
6 |
7 | The license chosen is at the discretion of the user of HIDAPI. For example:
8 | 1. An author of GPL software would likely use HIDAPI under the terms of the
9 | GPL.
10 |
11 | 2. An author of commercial closed-source software would likely use HIDAPI
12 | under the terms of the BSD-style license or the original HIDAPI license.
13 |
14 |
--------------------------------------------------------------------------------
/hidapi/Makefile.am:
--------------------------------------------------------------------------------
1 |
2 | ACLOCAL_AMFLAGS = -I m4
3 |
4 | if OS_FREEBSD
5 | pkgconfigdir=$(prefix)/libdata/pkgconfig
6 | else
7 | pkgconfigdir=$(libdir)/pkgconfig
8 | endif
9 |
10 | if OS_LINUX
11 | pkgconfig_DATA=pc/hidapi-hidraw.pc pc/hidapi-libusb.pc
12 | else
13 | pkgconfig_DATA=pc/hidapi.pc
14 | endif
15 |
16 | SUBDIRS=
17 |
18 | if OS_LINUX
19 | SUBDIRS += linux libusb
20 | endif
21 |
22 | if OS_DARWIN
23 | SUBDIRS += mac
24 | endif
25 |
26 | if OS_FREEBSD
27 | SUBDIRS += libusb
28 | endif
29 |
30 | if OS_KFREEBSD
31 | SUBDIRS += libusb
32 | endif
33 |
34 | if OS_WINDOWS
35 | SUBDIRS += windows
36 | endif
37 |
38 | SUBDIRS += hidtest
39 |
40 | if BUILD_TESTGUI
41 | SUBDIRS += testgui
42 | endif
43 |
44 | EXTRA_DIST = udev doxygen
45 |
46 | dist_doc_DATA = \
47 | README.md \
48 | AUTHORS.txt \
49 | LICENSE-bsd.txt \
50 | LICENSE-gpl3.txt \
51 | LICENSE-orig.txt \
52 | LICENSE.txt
53 |
54 | SCMCLEAN_TARGETS= \
55 | aclocal.m4 \
56 | config.guess \
57 | config.sub \
58 | configure \
59 | config.h.in \
60 | depcomp \
61 | install-sh \
62 | ltmain.sh \
63 | missing \
64 | mac/Makefile.in \
65 | testgui/Makefile.in \
66 | libusb/Makefile.in \
67 | Makefile.in \
68 | linux/Makefile.in \
69 | windows/Makefile.in \
70 | m4/libtool.m4 \
71 | m4/lt~obsolete.m4 \
72 | m4/ltoptions.m4 \
73 | m4/ltsugar.m4 \
74 | m4/ltversion.m4
75 |
76 | SCMCLEAN_DIR_TARGETS = \
77 | autom4te.cache
78 |
79 | scm-clean: distclean
80 | rm -f $(SCMCLEAN_TARGETS)
81 | rm -Rf $(SCMCLEAN_DIR_TARGETS)
82 |
--------------------------------------------------------------------------------
/hidapi/README.md:
--------------------------------------------------------------------------------
1 | ## HIDAPI library for Windows, Linux, FreeBSD and macOS
2 |
3 | | CI instance | Status |
4 | |----------------------|--------|
5 | | `macOS master` | [](https://travis-ci.org/libusb/hidapi) |
6 | | `Windows master` | [](https://ci.appveyor.com/project/Youw/hidapi/branch/master) |
7 | | `Linux/BSD, last build (branch/PR)` | [](https://builds.sr.ht/~qbicz/hidapi?) |
8 |
9 | HIDAPI is a multi-platform library which allows an application to interface
10 | with USB and Bluetooth HID-Class devices on Windows, Linux, FreeBSD, and macOS.
11 | HIDAPI can be either built as a shared library (`.so`, `.dll` or `.dylib`) or
12 | can be embedded directly into a target application by adding a single source
13 | file (per platform) and a single header.
14 |
15 | HIDAPI library was originally developed by Alan Ott ([signal11](https://github.com/signal11)).
16 |
17 | It was moved to [libusb/hidapi](https://github.com/libusb/hidapi) on June 4th, 2019, in order to merge important bugfixes and continue development of the library.
18 |
19 | ## Table of Contents
20 |
21 | * [About](#about)
22 | * [What Does the API Look Like?](#what-does-the-api-look-like)
23 | * [License](#license)
24 | * [Download](#download)
25 | * [Build Instructions](#build-instructions)
26 | * [Prerequisites](#prerequisites)
27 | * [Linux](#linux)
28 | * [FreeBSD](#freebsd)
29 | * [Mac](#mac)
30 | * [Windows](#windows)
31 | * [Building HIDAPI into a shared library on Unix Platforms](#building-hidapi-into-a-shared-library-on-unix-platforms)
32 | * [Building the manual way on Unix platforms](#building-the-manual-way-on-unix-platforms)
33 | * [Building on Windows](#building-on-windows)
34 | * [Cross Compiling](#cross-compiling)
35 | * [Prerequisites](#prerequisites-1)
36 | * [Building HIDAPI](#building-hidapi)
37 |
38 | ## About
39 |
40 | HIDAPI has five back-ends:
41 | * Windows (using `hid.dll`)
42 | * Linux/hidraw (using the Kernel's hidraw driver)
43 | * Linux/libusb (using libusb-1.0)
44 | * FreeBSD (using libusb-1.0)
45 | * Mac (using IOHidManager)
46 |
47 | On Linux, either the hidraw or the libusb back-end can be used. There are
48 | tradeoffs, and the functionality supported is slightly different.
49 |
50 | __Linux/hidraw__ (`linux/hid.c`):
51 |
52 | This back-end uses the hidraw interface in the Linux kernel, and supports
53 | both USB and Bluetooth HID devices. It requires kernel version at least 2.6.39
54 | to build. In addition, it will only communicate with devices which have hidraw
55 | nodes associated with them.
56 | Keyboards, mice, and some other devices which are blacklisted from having
57 | hidraw nodes will not work. Fortunately, for nearly all the uses of hidraw,
58 | this is not a problem.
59 |
60 | __Linux/FreeBSD/libusb__ (`libusb/hid.c`):
61 |
62 | This back-end uses libusb-1.0 to communicate directly to a USB device. This
63 | back-end will of course not work with Bluetooth devices.
64 |
65 | HIDAPI also comes with a Test GUI. The Test GUI is cross-platform and uses
66 | Fox Toolkit . It will build on every platform
67 | which HIDAPI supports. Since it relies on a 3rd party library, building it
68 | is optional but recommended because it is so useful when debugging hardware.
69 |
70 | ## What Does the API Look Like?
71 | The API provides the most commonly used HID functions including sending
72 | and receiving of input, output, and feature reports. The sample program,
73 | which communicates with a heavily hacked up version of the Microchip USB
74 | Generic HID sample looks like this (with error checking removed for
75 | simplicity):
76 |
77 | **Warning: Only run the code you understand, and only when it conforms to the
78 | device spec. Writing data at random to your HID devices can break them.**
79 |
80 | ```c
81 | #ifdef WIN32
82 | #include
83 | #endif
84 | #include
85 | #include
86 | #include "hidapi.h"
87 |
88 | #define MAX_STR 255
89 |
90 | int main(int argc, char* argv[])
91 | {
92 | int res;
93 | unsigned char buf[65];
94 | wchar_t wstr[MAX_STR];
95 | hid_device *handle;
96 | int i;
97 |
98 | // Initialize the hidapi library
99 | res = hid_init();
100 |
101 | // Open the device using the VID, PID,
102 | // and optionally the Serial number.
103 | handle = hid_open(0x4d8, 0x3f, NULL);
104 |
105 | // Read the Manufacturer String
106 | res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
107 | wprintf(L"Manufacturer String: %s\n", wstr);
108 |
109 | // Read the Product String
110 | res = hid_get_product_string(handle, wstr, MAX_STR);
111 | wprintf(L"Product String: %s\n", wstr);
112 |
113 | // Read the Serial Number String
114 | res = hid_get_serial_number_string(handle, wstr, MAX_STR);
115 | wprintf(L"Serial Number String: (%d) %s\n", wstr[0], wstr);
116 |
117 | // Read Indexed String 1
118 | res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
119 | wprintf(L"Indexed String 1: %s\n", wstr);
120 |
121 | // Toggle LED (cmd 0x80). The first byte is the report number (0x0).
122 | buf[0] = 0x0;
123 | buf[1] = 0x80;
124 | res = hid_write(handle, buf, 65);
125 |
126 | // Request state (cmd 0x81). The first byte is the report number (0x0).
127 | buf[0] = 0x0;
128 | buf[1] = 0x81;
129 | res = hid_write(handle, buf, 65);
130 |
131 | // Read requested state
132 | res = hid_read(handle, buf, 65);
133 |
134 | // Print out the returned buffer.
135 | for (i = 0; i < 4; i++)
136 | printf("buf[%d]: %d\n", i, buf[i]);
137 |
138 | // Close the device
139 | hid_close(handle);
140 |
141 | // Finalize the hidapi library
142 | res = hid_exit();
143 |
144 | return 0;
145 | }
146 | ```
147 |
148 | You can also use [hidtest/test.c](hidtest/test.c)
149 | as a starting point for your applications.
150 |
151 |
152 | ## License
153 | HIDAPI may be used by one of three licenses as outlined in [LICENSE.txt](LICENSE.txt).
154 |
155 | ## Download
156 | HIDAPI can be downloaded from GitHub
157 | ```sh
158 | git clone git://github.com/libusb/hidapi.git
159 | ```
160 |
161 | ## Build Instructions
162 |
163 | This section is long. Don't be put off by this. It's not long because it's
164 | complicated to build HIDAPI; it's quite the opposite. This section is long
165 | because of the flexibility of HIDAPI and the large number of ways in which
166 | it can be built and used. You will likely pick a single build method.
167 |
168 | HIDAPI can be built in several different ways. If you elect to build a
169 | shared library, you will need to build it from the HIDAPI source
170 | distribution. If you choose instead to embed HIDAPI directly into your
171 | application, you can skip the building and look at the provided platform
172 | Makefiles for guidance. These platform Makefiles are located in `linux/`,
173 | `libusb/`, `mac/` and `windows/` and are called `Makefile-manual`. In addition,
174 | Visual Studio projects are provided. Even if you're going to embed HIDAPI
175 | into your project, it is still beneficial to build the example programs.
176 |
177 |
178 | ### Prerequisites:
179 |
180 | #### Linux:
181 | On Linux, you will need to install development packages for libudev,
182 | libusb and optionally Fox-toolkit (for the test GUI). On
183 | Debian/Ubuntu systems these can be installed by running:
184 | ```sh
185 | sudo apt-get install libudev-dev libusb-1.0-0-dev libfox-1.6-dev
186 | ```
187 |
188 | If you downloaded the source directly from the git repository (using
189 | git clone), you'll need Autotools:
190 | ```sh
191 | sudo apt-get install autotools-dev autoconf automake libtool
192 | ```
193 |
194 | #### FreeBSD:
195 | On FreeBSD you will need to install GNU make, libiconv, and
196 | optionally Fox-Toolkit (for the test GUI). This is done by running
197 | the following:
198 | ```sh
199 | pkg_add -r gmake libiconv fox16
200 | ```
201 |
202 | If you downloaded the source directly from the git repository (using
203 | git clone), you'll need Autotools:
204 | ```sh
205 | pkg_add -r autotools
206 | ```
207 |
208 | #### Mac:
209 | On Mac, you will need to install Fox-Toolkit if you wish to build
210 | the Test GUI. There are two ways to do this, and each has a slight
211 | complication. Which method you use depends on your use case.
212 |
213 | If you wish to build the Test GUI just for your own testing on your
214 | own computer, then the easiest method is to install Fox-Toolkit
215 | using ports:
216 | ```sh
217 | sudo port install fox
218 | ```
219 |
220 | If you wish to build the TestGUI app bundle to redistribute to
221 | others, you will need to install Fox-toolkit from source. This is
222 | because the version of fox that gets installed using ports uses the
223 | ports X11 libraries which are not compatible with the Apple X11
224 | libraries. If you install Fox with ports and then try to distribute
225 | your built app bundle, it will simply fail to run on other systems.
226 | To install Fox-Toolkit manually, download the source package from
227 | , extract it, and run the following from
228 | within the extracted source:
229 | ```sh
230 | ./configure && make && make install
231 | ```
232 |
233 | #### Windows:
234 | On Windows, if you want to build the test GUI, you will need to get
235 | the `hidapi-externals.zip` package from the download site. This
236 | contains pre-built binaries for Fox-toolkit. Extract
237 | `hidapi-externals.zip` just outside of hidapi, so that
238 | hidapi-externals and hidapi are on the same level, as shown:
239 | ```
240 | Parent_Folder
241 | |
242 | +hidapi
243 | +hidapi-externals
244 | ```
245 | Again, this step is not required if you do not wish to build the
246 | test GUI.
247 |
248 |
249 | ### Building HIDAPI into a shared library on Unix Platforms:
250 |
251 | On Unix-like systems such as Linux, FreeBSD, macOS, and even Windows, using
252 | MinGW or Cygwin, the easiest way to build a standard system-installed shared
253 | library is to use the GNU Autotools build system. If you checked out the
254 | source from the git repository, run the following:
255 |
256 | ```sh
257 | ./bootstrap
258 | ./configure
259 | make
260 | make install # as root, or using sudo
261 | ```
262 |
263 | If you downloaded a source package (i.e.: if you did not run git clone), you
264 | can skip the `./bootstrap` step.
265 |
266 | `./configure` can take several arguments which control the build. The two most
267 | likely to be used are:
268 | ```sh
269 | --enable-testgui
270 | Enable build of the Test GUI. This requires Fox toolkit to
271 | be installed. Instructions for installing Fox-Toolkit on
272 | each platform are in the Prerequisites section above.
273 |
274 | --prefix=/usr
275 | Specify where you want the output headers and libraries to
276 | be installed. The example above will put the headers in
277 | /usr/include and the binaries in /usr/lib. The default is to
278 | install into /usr/local which is fine on most systems.
279 | ```
280 | ### Building the manual way on Unix platforms:
281 |
282 | Manual Makefiles are provided mostly to give the user and idea what it takes
283 | to build a program which embeds HIDAPI directly inside of it. These should
284 | really be used as examples only. If you want to build a system-wide shared
285 | library, use the Autotools method described above.
286 |
287 | To build HIDAPI using the manual Makefiles, change to the directory
288 | of your platform and run make. For example, on Linux run:
289 | ```sh
290 | cd linux/
291 | make -f Makefile-manual
292 | ```
293 |
294 | To build the Test GUI using the manual makefiles:
295 | ```sh
296 | cd testgui/
297 | make -f Makefile-manual
298 | ```
299 |
300 | ### Building on Windows:
301 |
302 | To build the HIDAPI DLL on Windows using Visual Studio, build the `.sln` file
303 | in the `windows/` directory.
304 |
305 | To build the Test GUI on windows using Visual Studio, build the `.sln` file in
306 | the `testgui/` directory.
307 |
308 | To build HIDAPI using MinGW or Cygwin using Autotools, use the instructions
309 | in the section [Building HIDAPI into a shared library on Unix Platforms](#building-hidapi-into-a-shared-library-on-unix-platforms)
310 | above. Note that building the Test GUI with MinGW or Cygwin will
311 | require the Windows procedure in the [Prerequisites](#prerequisites-1) section
312 | above (i.e.: `hidapi-externals.zip`).
313 |
314 | To build HIDAPI using MinGW using the Manual Makefiles, see the section
315 | [Building the manual way on Unix platforms](#building-the-manual-way-on-unix-platforms)
316 | above.
317 |
318 | HIDAPI can also be built using the Windows DDK (now also called the Windows
319 | Driver Kit or WDK). This method was originally required for the HIDAPI build
320 | but not anymore. However, some users still prefer this method. It is not as
321 | well supported anymore but should still work. Patches are welcome if it does
322 | not. To build using the DDK:
323 |
324 | 1. Install the Windows Driver Kit (WDK) from Microsoft.
325 | 2. From the Start menu, in the Windows Driver Kits folder, select Build
326 | Environments, then your operating system, then the x86 Free Build
327 | Environment (or one that is appropriate for your system).
328 | 3. From the console, change directory to the `windows/ddk_build/` directory,
329 | which is part of the HIDAPI distribution.
330 | 4. Type build.
331 | 5. You can find the output files (DLL and LIB) in a subdirectory created
332 | by the build system which is appropriate for your environment. On
333 | Windows XP, this directory is `objfre_wxp_x86/i386`.
334 |
335 | ## Cross Compiling
336 |
337 | This section talks about cross compiling HIDAPI for Linux using Autotools.
338 | This is useful for using HIDAPI on embedded Linux targets. These
339 | instructions assume the most raw kind of embedded Linux build, where all
340 | prerequisites will need to be built first. This process will of course vary
341 | based on your embedded Linux build system if you are using one, such as
342 | OpenEmbedded or Buildroot.
343 |
344 | For the purpose of this section, it will be assumed that the following
345 | environment variables are exported.
346 | ```sh
347 | $ export STAGING=$HOME/out
348 | $ export HOST=arm-linux
349 | ```
350 |
351 | `STAGING` and `HOST` can be modified to suit your setup.
352 |
353 | ### Prerequisites
354 |
355 | Note that the build of libudev is the very basic configuration.
356 |
357 | Build libusb. From the libusb source directory, run:
358 | ```sh
359 | ./configure --host=$HOST --prefix=$STAGING
360 | make
361 | make install
362 | ```
363 |
364 | Build libudev. From the libudev source directory, run:
365 | ```sh
366 | ./configure --disable-gudev --disable-introspection --disable-hwdb \
367 | --host=$HOST --prefix=$STAGING
368 | make
369 | make install
370 | ```
371 |
372 | ### Building HIDAPI
373 |
374 | Build HIDAPI:
375 | ```
376 | PKG_CONFIG_DIR= \
377 | PKG_CONFIG_LIBDIR=$STAGING/lib/pkgconfig:$STAGING/share/pkgconfig \
378 | PKG_CONFIG_SYSROOT_DIR=$STAGING \
379 | ./configure --host=$HOST --prefix=$STAGING
380 | ```
381 |
--------------------------------------------------------------------------------
/hidapi/android/jni/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH:= $(call my-dir)
2 |
3 | HIDAPI_ROOT_REL:= ../..
4 | HIDAPI_ROOT_ABS:= $(LOCAL_PATH)/../..
5 |
6 | include $(CLEAR_VARS)
7 |
8 | LOCAL_SRC_FILES := \
9 | $(HIDAPI_ROOT_REL)/libusb/hid.c
10 |
11 | LOCAL_C_INCLUDES += \
12 | $(HIDAPI_ROOT_ABS)/hidapi \
13 | $(HIDAPI_ROOT_ABS)/android
14 |
15 | LOCAL_SHARED_LIBRARIES := libusb1.0
16 |
17 | LOCAL_MODULE := libhidapi
18 |
19 | include $(BUILD_SHARED_LIBRARY)
20 |
--------------------------------------------------------------------------------
/hidapi/bootstrap:
--------------------------------------------------------------------------------
1 | #!/bin/sh -x
2 | autoreconf --install --verbose --force
3 |
--------------------------------------------------------------------------------
/hidapi/configure.ac:
--------------------------------------------------------------------------------
1 | AC_PREREQ(2.63)
2 |
3 | # Version number. This is currently the only place.
4 | m4_define([HIDAPI_MAJOR], 0)
5 | m4_define([HIDAPI_MINOR], 9)
6 | m4_define([HIDAPI_RELEASE], 0)
7 | m4_define([HIDAPI_RC], )
8 | m4_define([VERSION_STRING], HIDAPI_MAJOR[.]HIDAPI_MINOR[.]HIDAPI_RELEASE[]HIDAPI_RC)
9 |
10 | AC_INIT([hidapi],[VERSION_STRING],[alan@signal11.us])
11 |
12 | # Library soname version
13 | # Follow the following rules (particularly the ones in the second link):
14 | # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
15 | # http://sourceware.org/autobook/autobook/autobook_91.html
16 | lt_current="0"
17 | lt_revision="0"
18 | lt_age="0"
19 | LTLDFLAGS="-version-info ${lt_current}:${lt_revision}:${lt_age}"
20 |
21 | AC_CONFIG_MACRO_DIR([m4])
22 | AM_INIT_AUTOMAKE([foreign -Wall -Werror])
23 | AC_CONFIG_MACRO_DIR([m4])
24 |
25 | m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
26 | LT_INIT
27 |
28 | AC_PROG_CC
29 | AC_PROG_CXX
30 | AC_PROG_OBJC
31 | PKG_PROG_PKG_CONFIG
32 |
33 |
34 | m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
35 |
36 | hidapi_lib_error() {
37 | echo ""
38 | echo " Library $1 was not found on this system."
39 | echo " Please install it and re-run ./configure"
40 | echo ""
41 | exit 1
42 | }
43 |
44 | hidapi_prog_error() {
45 | echo ""
46 | echo " Program $1 was not found on this system."
47 | echo " This program is part of $2."
48 | echo " Please install it and re-run ./configure"
49 | echo ""
50 | exit 1
51 | }
52 |
53 | AC_MSG_CHECKING([operating system])
54 | AC_MSG_RESULT($host)
55 | case $host in
56 | *-linux*)
57 | AC_MSG_RESULT([ (Linux back-end)])
58 | AC_DEFINE(OS_LINUX, 1, [Linux implementations])
59 | AC_SUBST(OS_LINUX)
60 | backend="linux"
61 | os="linux"
62 | threads="pthreads"
63 |
64 | # HIDAPI/hidraw libs
65 | PKG_CHECK_MODULES([libudev], [libudev], true, [hidapi_lib_error libudev])
66 | LIBS_HIDRAW_PR="${LIBS_HIDRAW_PR} $libudev_LIBS"
67 | CFLAGS_HIDRAW="${CFLAGS_HIDRAW} $libudev_CFLAGS"
68 |
69 | # HIDAPI/libusb libs
70 | AC_CHECK_LIB([rt], [clock_gettime], [LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} -lrt"], [hidapi_lib_error librt])
71 | PKG_CHECK_MODULES([libusb], [libusb-1.0 >= 1.0.9], true, [hidapi_lib_error libusb-1.0])
72 | LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} $libusb_LIBS"
73 | CFLAGS_LIBUSB="${CFLAGS_LIBUSB} $libusb_CFLAGS"
74 | ;;
75 | *-darwin*)
76 | AC_MSG_RESULT([ (Mac OS X back-end)])
77 | AC_DEFINE(OS_DARWIN, 1, [Mac implementation])
78 | AC_SUBST(OS_DARWIN)
79 | backend="mac"
80 | os="darwin"
81 | threads="pthreads"
82 | LIBS="${LIBS} -framework IOKit -framework CoreFoundation"
83 | ;;
84 | *-freebsd*)
85 | AC_MSG_RESULT([ (FreeBSD back-end)])
86 | AC_DEFINE(OS_FREEBSD, 1, [FreeBSD implementation])
87 | AC_SUBST(OS_FREEBSD)
88 | backend="libusb"
89 | os="freebsd"
90 | threads="pthreads"
91 |
92 | CFLAGS="$CFLAGS -I/usr/local/include"
93 | LDFLAGS="$LDFLAGS -L/usr/local/lib"
94 | LIBS="${LIBS}"
95 | PKG_CHECK_MODULES([libusb], [libusb-1.0 >= 1.0.9], true, [hidapi_lib_error libusb-1.0])
96 | LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} $libusb_LIBS"
97 | CFLAGS_LIBUSB="${CFLAGS_LIBUSB} $libusb_CFLAGS"
98 | AC_CHECK_LIB([iconv], [iconv_open], [LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} -liconv"], [hidapi_lib_error libiconv])
99 | ;;
100 | *-kfreebsd*)
101 | AC_MSG_RESULT([ (kFreeBSD back-end)])
102 | AC_DEFINE(OS_KFREEBSD, 1, [kFreeBSD implementation])
103 | AC_SUBST(OS_KFREEBSD)
104 | backend="libusb"
105 | os="kfreebsd"
106 | threads="pthreads"
107 |
108 | PKG_CHECK_MODULES([libusb], [libusb-1.0 >= 1.0.9], true, [hidapi_lib_error libusb-1.0])
109 | LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} $libusb_LIBS"
110 | CFLAGS_LIBUSB="${CFLAGS_LIBUSB} $libusb_CFLAGS"
111 | ;;
112 | *-mingw*)
113 | AC_MSG_RESULT([ (Windows back-end, using MinGW)])
114 | backend="windows"
115 | os="windows"
116 | threads="windows"
117 | win_implementation="mingw"
118 | ;;
119 | *-cygwin*)
120 | AC_MSG_RESULT([ (Windows back-end, using Cygwin)])
121 | backend="windows"
122 | os="windows"
123 | threads="windows"
124 | win_implementation="cygwin"
125 | ;;
126 | *)
127 | AC_MSG_ERROR([HIDAPI is not supported on your operating system yet])
128 | esac
129 |
130 | LIBS_HIDRAW="${LIBS} ${LIBS_HIDRAW_PR}"
131 | LIBS_LIBUSB="${LIBS} ${LIBS_LIBUSB_PRIVATE}"
132 | AC_SUBST([LIBS_HIDRAW])
133 | AC_SUBST([LIBS_LIBUSB])
134 | AC_SUBST([CFLAGS_LIBUSB])
135 | AC_SUBST([CFLAGS_HIDRAW])
136 |
137 | if test "x$os" = xwindows; then
138 | AC_DEFINE(OS_WINDOWS, 1, [Windows implementations])
139 | AC_SUBST(OS_WINDOWS)
140 | LDFLAGS="${LDFLAGS} -no-undefined"
141 | LIBS="${LIBS} -lsetupapi"
142 | fi
143 |
144 | if test "x$threads" = xpthreads; then
145 | AX_PTHREAD([found_pthreads=yes], [found_pthreads=no])
146 |
147 | if test "x$found_pthreads" = xyes; then
148 | if test "x$os" = xlinux; then
149 | # Only use pthreads for libusb implementation on Linux.
150 | LIBS_LIBUSB="$PTHREAD_LIBS $LIBS_LIBUSB"
151 | CFLAGS_LIBUSB="$CFLAGS_LIBUSB $PTHREAD_CFLAGS"
152 | # There's no separate CC on Linux for threading,
153 | # so it's ok that both implementations use $PTHREAD_CC
154 | CC="$PTHREAD_CC"
155 | else
156 | LIBS="$PTHREAD_LIBS $LIBS"
157 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
158 | CC="$PTHREAD_CC"
159 | fi
160 | fi
161 | fi
162 |
163 | # Test GUI
164 | AC_ARG_ENABLE([testgui],
165 | [AS_HELP_STRING([--enable-testgui],
166 | [enable building of test GUI (default n)])],
167 | [testgui_enabled=$enableval],
168 | [testgui_enabled='no'])
169 | AM_CONDITIONAL([BUILD_TESTGUI], [test "x$testgui_enabled" != "xno"])
170 |
171 | # Configure the MacOS TestGUI app bundle
172 | rm -Rf testgui/TestGUI.app
173 | mkdir -p testgui/TestGUI.app
174 | cp -R ${srcdir}/testgui/TestGUI.app.in/* testgui/TestGUI.app
175 | chmod -R u+w testgui/TestGUI.app
176 | mkdir testgui/TestGUI.app/Contents/MacOS/
177 |
178 | if test "x$testgui_enabled" != "xno"; then
179 | if test "x$os" = xdarwin; then
180 | # On Mac OS, don't use pkg-config.
181 | AC_CHECK_PROG([foxconfig], [fox-config], [fox-config], false)
182 | if test "x$foxconfig" = "xfalse"; then
183 | hidapi_prog_error fox-config "FOX Toolkit"
184 | fi
185 | LIBS_TESTGUI="${LIBS_TESTGUI} `$foxconfig --libs`"
186 | LIBS_TESTGUI="${LIBS_TESTGUI} -framework Cocoa -L/usr/X11R6/lib"
187 | CFLAGS_TESTGUI="${CFLAGS_TESTGUI} `$foxconfig --cflags`"
188 | OBJCFLAGS="${OBJCFLAGS} -x objective-c++"
189 | elif test "x$os" = xwindows; then
190 | # On Windows, just set the paths for Fox toolkit
191 | if test "x$win_implementation" = xmingw; then
192 | CFLAGS_TESTGUI="-I\$(srcdir)/../../hidapi-externals/fox/include -g -c"
193 | LIBS_TESTGUI=" -mwindows \$(srcdir)/../../hidapi-externals/fox/lib/libFOX-1.6.a -lgdi32 -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lkernel32"
194 | else
195 | # Cygwin
196 | CFLAGS_TESTGUI="-DWIN32 -I\$(srcdir)/../../hidapi-externals/fox/include -g -c"
197 | LIBS_TESTGUI="\$(srcdir)/../../hidapi-externals/fox/lib/libFOX-cygwin-1.6.a -lgdi32 -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lkernel32"
198 | fi
199 | else
200 | # On Linux and FreeBSD platforms, use pkg-config to find fox.
201 | PKG_CHECK_MODULES([fox], [fox17], [], [PKG_CHECK_MODULES([fox], [fox])])
202 | LIBS_TESTGUI="${LIBS_TESTGUI} $fox_LIBS"
203 | if test "x$os" = xfreebsd; then
204 | LIBS_TESTGUI="${LIBS_TESTGUI} -L/usr/local/lib"
205 | fi
206 | CFLAGS_TESTGUI="${CFLAGS_TESTGUI} $fox_CFLAGS"
207 | fi
208 | fi
209 | AC_SUBST([LIBS_TESTGUI])
210 | AC_SUBST([CFLAGS_TESTGUI])
211 | AC_SUBST([backend])
212 |
213 | # OS info for Automake
214 | AM_CONDITIONAL(OS_LINUX, test "x$os" = xlinux)
215 | AM_CONDITIONAL(OS_DARWIN, test "x$os" = xdarwin)
216 | AM_CONDITIONAL(OS_FREEBSD, test "x$os" = xfreebsd)
217 | AM_CONDITIONAL(OS_KFREEBSD, test "x$os" = xkfreebsd)
218 | AM_CONDITIONAL(OS_WINDOWS, test "x$os" = xwindows)
219 |
220 | AC_CONFIG_HEADERS([config.h])
221 |
222 | if test "x$os" = "xlinux"; then
223 | AC_CONFIG_FILES([pc/hidapi-hidraw.pc])
224 | AC_CONFIG_FILES([pc/hidapi-libusb.pc])
225 | else
226 | AC_CONFIG_FILES([pc/hidapi.pc])
227 | fi
228 |
229 | AC_SUBST(LTLDFLAGS)
230 |
231 | AC_CONFIG_FILES([Makefile \
232 | hidtest/Makefile \
233 | libusb/Makefile \
234 | linux/Makefile \
235 | mac/Makefile \
236 | testgui/Makefile \
237 | windows/Makefile])
238 | AC_OUTPUT
239 |
--------------------------------------------------------------------------------
/hidapi/dist/hidapi.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |spec|
2 |
3 | spec.name = "hidapi"
4 | spec.version = "0.9.0"
5 | spec.summary = "A Simple library for communicating with USB and Bluetooth HID devices on Linux, Mac and Windows."
6 |
7 | spec.description = <<-DESC
8 | HIDAPI is a multi-platform library which allows an application to interface with USB and Bluetooth HID-Class devices on Windows, Linux, FreeBSD, and macOS. HIDAPI can be either built as a shared library (.so, .dll or .dylib) or can be embedded directly into a target application by adding a single source file (per platform) and a single header.
9 | DESC
10 |
11 | spec.homepage = "https://github.com/libusb/hidapi"
12 |
13 | spec.license = { :type=> "GNU GPLv3 or BSD or HIDAPI original", :file => "LICENSE.txt" }
14 |
15 | spec.authors = { "Alan Ott" => "alan@signal11.us",
16 | "Ludovic Rousseau" => "rousseau@debian.org",
17 | "libusb/hidapi Team" => "https://github.com/libusb/hidapi/blob/master/AUTHORS.txt",
18 | }
19 |
20 | spec.platform = :osx
21 | spec.osx.deployment_target = "10.7"
22 |
23 | spec.source = { :git => "https://github.com/libusb/hidapi.git", :tag => "hidapi-#{spec.version}" }
24 |
25 | spec.source_files = "mac/hid.c", "hidapi/hidapi.h"
26 |
27 | spec.public_header_files = "hidapi/hidapi.h"
28 |
29 | spec.frameworks = "IOKit", "CoreFoundation"
30 |
31 | end
32 |
--------------------------------------------------------------------------------
/hidapi/hidtest/.gitignore:
--------------------------------------------------------------------------------
1 | Debug
2 | Release
3 | *.exp
4 | *.ilk
5 | *.lib
6 | *.suo
7 | *.vcproj.*
8 | *.ncb
9 | *.suo
10 | *.dll
11 | *.pdb
12 | *.o
13 | .deps/
14 | .libs/
15 | hidtest-hidraw
16 | hidtest-libusb
17 | hidtest
18 |
--------------------------------------------------------------------------------
/hidapi/hidtest/Makefile.am:
--------------------------------------------------------------------------------
1 | AM_CPPFLAGS = -I$(top_srcdir)/hidapi/
2 |
3 | ## Linux
4 | if OS_LINUX
5 | noinst_PROGRAMS = hidtest-libusb hidtest-hidraw
6 |
7 | hidtest_hidraw_SOURCES = test.c
8 | hidtest_hidraw_LDADD = $(top_builddir)/linux/libhidapi-hidraw.la
9 |
10 | hidtest_libusb_SOURCES = test.c
11 | hidtest_libusb_LDADD = $(top_builddir)/libusb/libhidapi-libusb.la
12 | else
13 |
14 | # Other OS's
15 | noinst_PROGRAMS = hidtest
16 |
17 | hidtest_SOURCES = test.c
18 | hidtest_LDADD = $(top_builddir)/$(backend)/libhidapi.la
19 |
20 | endif
21 |
--------------------------------------------------------------------------------
/hidapi/hidtest/test.c:
--------------------------------------------------------------------------------
1 | /*******************************************************
2 | Windows HID simplification
3 |
4 | Alan Ott
5 | Signal 11 Software
6 |
7 | 8/22/2009
8 |
9 | Copyright 2009
10 |
11 | This contents of this file may be used by anyone
12 | for any reason without any conditions and may be
13 | used as a starting point for your own applications
14 | which use HIDAPI.
15 | ********************************************************/
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include "hidapi.h"
22 |
23 | // Headers needed for sleeping.
24 | #ifdef _WIN32
25 | #include
26 | #else
27 | #include
28 | #endif
29 |
30 | int main(int argc, char* argv[])
31 | {
32 | int res;
33 | unsigned char buf[256];
34 | #define MAX_STR 255
35 | wchar_t wstr[MAX_STR];
36 | hid_device *handle;
37 | int i;
38 |
39 | #ifdef WIN32
40 | UNREFERENCED_PARAMETER(argc);
41 | UNREFERENCED_PARAMETER(argv);
42 | #endif
43 |
44 | struct hid_device_info *devs, *cur_dev;
45 |
46 | if (hid_init())
47 | return -1;
48 |
49 | devs = hid_enumerate(0x0, 0x0);
50 | cur_dev = devs;
51 | while (cur_dev) {
52 | printf("Device Found\n type: %04hx %04hx\n path: %s\n serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
53 | printf("\n");
54 | printf(" Manufacturer: %ls\n", cur_dev->manufacturer_string);
55 | printf(" Product: %ls\n", cur_dev->product_string);
56 | printf(" Release: %hx\n", cur_dev->release_number);
57 | printf(" Interface: %d\n", cur_dev->interface_number);
58 | printf("\n");
59 | cur_dev = cur_dev->next;
60 | }
61 | hid_free_enumeration(devs);
62 |
63 | // Set up the command buffer.
64 | memset(buf,0x00,sizeof(buf));
65 | buf[0] = 0x01;
66 | buf[1] = 0x81;
67 |
68 |
69 | // Open the device using the VID, PID,
70 | // and optionally the Serial number.
71 | ////handle = hid_open(0x4d8, 0x3f, L"12345");
72 | handle = hid_open(0x4d8, 0x3f, NULL);
73 | if (!handle) {
74 | printf("unable to open device\n");
75 | return 1;
76 | }
77 |
78 | // Read the Manufacturer String
79 | wstr[0] = 0x0000;
80 | res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
81 | if (res < 0)
82 | printf("Unable to read manufacturer string\n");
83 | printf("Manufacturer String: %ls\n", wstr);
84 |
85 | // Read the Product String
86 | wstr[0] = 0x0000;
87 | res = hid_get_product_string(handle, wstr, MAX_STR);
88 | if (res < 0)
89 | printf("Unable to read product string\n");
90 | printf("Product String: %ls\n", wstr);
91 |
92 | // Read the Serial Number String
93 | wstr[0] = 0x0000;
94 | res = hid_get_serial_number_string(handle, wstr, MAX_STR);
95 | if (res < 0)
96 | printf("Unable to read serial number string\n");
97 | printf("Serial Number String: (%d) %ls", wstr[0], wstr);
98 | printf("\n");
99 |
100 | // Read Indexed String 1
101 | wstr[0] = 0x0000;
102 | res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
103 | if (res < 0)
104 | printf("Unable to read indexed string 1\n");
105 | printf("Indexed String 1: %ls\n", wstr);
106 |
107 | // Set the hid_read() function to be non-blocking.
108 | hid_set_nonblocking(handle, 1);
109 |
110 | // Try to read from the device. There should be no
111 | // data here, but execution should not block.
112 | res = hid_read(handle, buf, 17);
113 |
114 | // Send a Feature Report to the device
115 | buf[0] = 0x2;
116 | buf[1] = 0xa0;
117 | buf[2] = 0x0a;
118 | buf[3] = 0x00;
119 | buf[4] = 0x00;
120 | res = hid_send_feature_report(handle, buf, 17);
121 | if (res < 0) {
122 | printf("Unable to send a feature report.\n");
123 | }
124 |
125 | memset(buf,0,sizeof(buf));
126 |
127 | // Read a Feature Report from the device
128 | buf[0] = 0x2;
129 | res = hid_get_feature_report(handle, buf, sizeof(buf));
130 | if (res < 0) {
131 | printf("Unable to get a feature report.\n");
132 | printf("%ls", hid_error(handle));
133 | }
134 | else {
135 | // Print out the returned buffer.
136 | printf("Feature Report\n ");
137 | for (i = 0; i < res; i++)
138 | printf("%02hhx ", buf[i]);
139 | printf("\n");
140 | }
141 |
142 | memset(buf,0,sizeof(buf));
143 |
144 | // Toggle LED (cmd 0x80). The first byte is the report number (0x1).
145 | buf[0] = 0x1;
146 | buf[1] = 0x80;
147 | res = hid_write(handle, buf, 17);
148 | if (res < 0) {
149 | printf("Unable to write()\n");
150 | printf("Error: %ls\n", hid_error(handle));
151 | }
152 |
153 |
154 | // Request state (cmd 0x81). The first byte is the report number (0x1).
155 | buf[0] = 0x1;
156 | buf[1] = 0x81;
157 | hid_write(handle, buf, 17);
158 | if (res < 0)
159 | printf("Unable to write() (2)\n");
160 |
161 | // Read requested state. hid_read() has been set to be
162 | // non-blocking by the call to hid_set_nonblocking() above.
163 | // This loop demonstrates the non-blocking nature of hid_read().
164 | res = 0;
165 | while (res == 0) {
166 | res = hid_read(handle, buf, sizeof(buf));
167 | if (res == 0)
168 | printf("waiting...\n");
169 | if (res < 0)
170 | printf("Unable to read()\n");
171 | #ifdef WIN32
172 | Sleep(500);
173 | #else
174 | usleep(500*1000);
175 | #endif
176 | }
177 |
178 | printf("Data read:\n ");
179 | // Print out the returned buffer.
180 | for (i = 0; i < res; i++)
181 | printf("%02hhx ", buf[i]);
182 | printf("\n");
183 |
184 | hid_close(handle);
185 |
186 | /* Free static HIDAPI objects. */
187 | hid_exit();
188 |
189 | #ifdef WIN32
190 | system("pause");
191 | #endif
192 |
193 | return 0;
194 | }
195 |
--------------------------------------------------------------------------------
/hidapi/libusb/.gitignore:
--------------------------------------------------------------------------------
1 | *.o
2 | *.so
3 | *.la
4 | *.lo
5 | *.a
6 | .libs
7 | .deps
8 | hidtest-libusb
9 |
--------------------------------------------------------------------------------
/hidapi/libusb/Makefile-manual:
--------------------------------------------------------------------------------
1 |
2 |
3 | OS=$(shell uname)
4 |
5 | ifeq ($(OS), Linux)
6 | FILE=Makefile.linux
7 | endif
8 |
9 | ifeq ($(OS), FreeBSD)
10 | FILE=Makefile.freebsd
11 | endif
12 |
13 | ifeq ($(FILE), )
14 | all:
15 | $(error Your platform ${OS} is not supported by hidapi/libusb at this time.)
16 | endif
17 |
18 | include $(FILE)
19 |
--------------------------------------------------------------------------------
/hidapi/libusb/Makefile.am:
--------------------------------------------------------------------------------
1 | AM_CPPFLAGS = -I$(top_srcdir)/hidapi $(CFLAGS_LIBUSB)
2 |
3 | if OS_LINUX
4 | lib_LTLIBRARIES = libhidapi-libusb.la
5 | libhidapi_libusb_la_SOURCES = hid.c
6 | libhidapi_libusb_la_LDFLAGS = $(LTLDFLAGS) $(PTHREAD_CFLAGS)
7 | libhidapi_libusb_la_LIBADD = $(LIBS_LIBUSB)
8 | endif
9 |
10 | if OS_FREEBSD
11 | lib_LTLIBRARIES = libhidapi.la
12 | libhidapi_la_SOURCES = hid.c
13 | libhidapi_la_LDFLAGS = $(LTLDFLAGS)
14 | libhidapi_la_LIBADD = $(LIBS_LIBUSB)
15 | endif
16 |
17 | if OS_KFREEBSD
18 | lib_LTLIBRARIES = libhidapi.la
19 | libhidapi_la_SOURCES = hid.c
20 | libhidapi_la_LDFLAGS = $(LTLDFLAGS)
21 | libhidapi_la_LIBADD = $(LIBS_LIBUSB)
22 | endif
23 |
24 | hdrdir = $(includedir)/hidapi
25 | hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h
26 |
27 | EXTRA_DIST = Makefile-manual
28 |
--------------------------------------------------------------------------------
/hidapi/libusb/Makefile.freebsd:
--------------------------------------------------------------------------------
1 | ###########################################
2 | # Simple Makefile for HIDAPI test program
3 | #
4 | # Alan Ott
5 | # Signal 11 Software
6 | # 2010-06-01
7 | ###########################################
8 |
9 | all: hidtest libs
10 |
11 | libs: libhidapi.so
12 |
13 | CC ?= cc
14 | CFLAGS ?= -Wall -g -fPIC
15 |
16 | CXX ?= c++
17 | CXXFLAGS ?= -Wall -g
18 |
19 | COBJS = hid.o
20 | CPPOBJS = ../hidtest/hidtest.o
21 | OBJS = $(COBJS) $(CPPOBJS)
22 | INCLUDES = -I../hidapi -I/usr/local/include
23 | LDFLAGS = -L/usr/local/lib
24 | LIBS = -lusb -liconv -pthread
25 |
26 |
27 | # Console Test Program
28 | hidtest: $(OBJS)
29 | $(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS)
30 |
31 | # Shared Libs
32 | libhidapi.so: $(COBJS)
33 | $(CC) $(LDFLAGS) -shared -Wl,-soname,$@.0 $^ -o $@ $(LIBS)
34 |
35 | # Objects
36 | $(COBJS): %.o: %.c
37 | $(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@
38 |
39 | $(CPPOBJS): %.o: %.cpp
40 | $(CXX) $(CXXFLAGS) -c $(INCLUDES) $< -o $@
41 |
42 |
43 | clean:
44 | rm -f $(OBJS) hidtest libhidapi.so ../hidtest/hidtest.o
45 |
46 | .PHONY: clean libs
47 |
--------------------------------------------------------------------------------
/hidapi/libusb/Makefile.linux:
--------------------------------------------------------------------------------
1 | ###########################################
2 | # Simple Makefile for HIDAPI test program
3 | #
4 | # Alan Ott
5 | # Signal 11 Software
6 | # 2010-06-01
7 | ###########################################
8 |
9 | all: hidtest-libusb libs
10 |
11 | libs: libhidapi-libusb.so
12 |
13 | CC ?= gcc
14 | CFLAGS ?= -Wall -g -fpic
15 |
16 | CXX ?= g++
17 | CXXFLAGS ?= -Wall -g -fpic
18 |
19 | LDFLAGS ?= -Wall -g
20 |
21 | COBJS_LIBUSB = hid.o
22 | COBJS = $(COBJS_LIBUSB)
23 | CPPOBJS = ../hidtest/hidtest.o
24 | OBJS = $(COBJS) $(CPPOBJS)
25 | LIBS_USB = `pkg-config libusb-1.0 --libs` -lrt -lpthread
26 | LIBS = $(LIBS_USB)
27 | INCLUDES ?= -I../hidapi `pkg-config libusb-1.0 --cflags`
28 |
29 |
30 | # Console Test Program
31 | hidtest-libusb: $(COBJS_LIBUSB) $(CPPOBJS)
32 | $(CXX) $(LDFLAGS) $^ $(LIBS_USB) -o $@
33 |
34 | # Shared Libs
35 | libhidapi-libusb.so: $(COBJS_LIBUSB)
36 | $(CC) $(LDFLAGS) $(LIBS_USB) -shared -fpic -Wl,-soname,$@.0 $^ -o $@
37 |
38 | # Objects
39 | $(COBJS): %.o: %.c
40 | $(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@
41 |
42 | $(CPPOBJS): %.o: %.cpp
43 | $(CXX) $(CXXFLAGS) -c $(INCLUDES) $< -o $@
44 |
45 |
46 | clean:
47 | rm -f $(OBJS) hidtest-libusb libhidapi-libusb.so ../hidtest/hidtest.o
48 |
49 | .PHONY: clean libs
50 |
--------------------------------------------------------------------------------
/hidapi/linux/.gitignore:
--------------------------------------------------------------------------------
1 | Debug
2 | Release
3 | *.exp
4 | *.ilk
5 | *.lib
6 | *.suo
7 | *.vcproj.*
8 | *.ncb
9 | *.suo
10 | *.dll
11 | *.pdb
12 | *.o
13 | *.so
14 | hidtest-hidraw
15 | .deps
16 | .libs
17 | *.lo
18 | *.la
19 |
--------------------------------------------------------------------------------
/hidapi/linux/Makefile-manual:
--------------------------------------------------------------------------------
1 | ###########################################
2 | # Simple Makefile for HIDAPI test program
3 | #
4 | # Alan Ott
5 | # Signal 11 Software
6 | # 2010-06-01
7 | ###########################################
8 |
9 | all: hidtest-hidraw libs
10 |
11 | libs: libhidapi-hidraw.so
12 |
13 | CC ?= gcc
14 | CFLAGS ?= -Wall -g -fpic
15 |
16 | CXX ?= g++
17 | CXXFLAGS ?= -Wall -g -fpic
18 |
19 | LDFLAGS ?= -Wall -g
20 |
21 |
22 | COBJS = hid.o ../hidtest/test.o
23 | CPPOBJS =
24 | OBJS = $(COBJS) $(CPPOBJS)
25 | LIBS_UDEV = `pkg-config libudev --libs` -lrt
26 | LIBS = $(LIBS_UDEV)
27 | INCLUDES ?= -I../hidapi `pkg-config libusb-1.0 --cflags`
28 |
29 |
30 | # Console Test Program
31 | hidtest-hidraw: $(COBJS) $(CPPOBJS)
32 | $(CC) $(LDFLAGS) $^ $(LIBS_UDEV) -o $@
33 |
34 | # Shared Libs
35 | libhidapi-hidraw.so: $(COBJS)
36 | $(CC) $(LDFLAGS) $(LIBS_UDEV) -shared -fpic -Wl,-soname,$@.0 $^ -o $@
37 |
38 | # Objects
39 | $(COBJS): %.o: %.c
40 | $(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@
41 |
42 | $(CPPOBJS): %.o: %.cpp
43 | $(CXX) $(CXXFLAGS) -c $(INCLUDES) $< -o $@
44 |
45 |
46 | clean:
47 | rm -f $(OBJS) hidtest-hidraw libhidapi-hidraw.so $(COBJS) $(CPPOBJS)
48 |
49 | .PHONY: clean libs
50 |
--------------------------------------------------------------------------------
/hidapi/linux/Makefile.am:
--------------------------------------------------------------------------------
1 | lib_LTLIBRARIES = libhidapi-hidraw.la
2 | libhidapi_hidraw_la_SOURCES = hid.c
3 | libhidapi_hidraw_la_LDFLAGS = $(LTLDFLAGS)
4 | AM_CPPFLAGS = -I$(top_srcdir)/hidapi/ $(CFLAGS_HIDRAW)
5 | libhidapi_hidraw_la_LIBADD = $(LIBS_HIDRAW)
6 |
7 | hdrdir = $(includedir)/hidapi
8 | hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h
9 |
10 | EXTRA_DIST = Makefile-manual
11 |
--------------------------------------------------------------------------------
/hidapi/m4/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore All, except pkg.m4, and of course this file.
2 | *
3 | !.gitignore
4 | !pkg.m4
5 | !ax_pthread.m4
6 |
--------------------------------------------------------------------------------
/hidapi/m4/ax_pthread.m4:
--------------------------------------------------------------------------------
1 | # ===========================================================================
2 | # http://www.gnu.org/software/autoconf-archive/ax_pthread.html
3 | # ===========================================================================
4 | #
5 | # SYNOPSIS
6 | #
7 | # AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
8 | #
9 | # DESCRIPTION
10 | #
11 | # This macro figures out how to build C programs using POSIX threads. It
12 | # sets the PTHREAD_LIBS output variable to the threads library and linker
13 | # flags, and the PTHREAD_CFLAGS output variable to any special C compiler
14 | # flags that are needed. (The user can also force certain compiler
15 | # flags/libs to be tested by setting these environment variables.)
16 | #
17 | # Also sets PTHREAD_CC to any special C compiler that is needed for
18 | # multi-threaded programs (defaults to the value of CC otherwise). (This
19 | # is necessary on AIX to use the special cc_r compiler alias.)
20 | #
21 | # NOTE: You are assumed to not only compile your program with these flags,
22 | # but also link it with them as well. e.g. you should link with
23 | # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
24 | #
25 | # If you are only building threads programs, you may wish to use these
26 | # variables in your default LIBS, CFLAGS, and CC:
27 | #
28 | # LIBS="$PTHREAD_LIBS $LIBS"
29 | # CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
30 | # CC="$PTHREAD_CC"
31 | #
32 | # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
33 | # has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
34 | # (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
35 | #
36 | # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
37 | # PTHREAD_PRIO_INHERIT symbol is defined when compiling with
38 | # PTHREAD_CFLAGS.
39 | #
40 | # ACTION-IF-FOUND is a list of shell commands to run if a threads library
41 | # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
42 | # is not found. If ACTION-IF-FOUND is not specified, the default action
43 | # will define HAVE_PTHREAD.
44 | #
45 | # Please let the authors know if this macro fails on any platform, or if
46 | # you have any other suggestions or comments. This macro was based on work
47 | # by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
48 | # from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
49 | # Alejandro Forero Cuervo to the autoconf macro repository. We are also
50 | # grateful for the helpful feedback of numerous users.
51 | #
52 | # Updated for Autoconf 2.68 by Daniel Richard G.
53 | #
54 | # LICENSE
55 | #
56 | # Copyright (c) 2008 Steven G. Johnson
57 | # Copyright (c) 2011 Daniel Richard G.
58 | #
59 | # This program is free software: you can redistribute it and/or modify it
60 | # under the terms of the GNU General Public License as published by the
61 | # Free Software Foundation, either version 3 of the License, or (at your
62 | # option) any later version.
63 | #
64 | # This program is distributed in the hope that it will be useful, but
65 | # WITHOUT ANY WARRANTY; without even the implied warranty of
66 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
67 | # Public License for more details.
68 | #
69 | # You should have received a copy of the GNU General Public License along
70 | # with this program. If not, see .
71 | #
72 | # As a special exception, the respective Autoconf Macro's copyright owner
73 | # gives unlimited permission to copy, distribute and modify the configure
74 | # scripts that are the output of Autoconf when processing the Macro. You
75 | # need not follow the terms of the GNU General Public License when using
76 | # or distributing such scripts, even though portions of the text of the
77 | # Macro appear in them. The GNU General Public License (GPL) does govern
78 | # all other use of the material that constitutes the Autoconf Macro.
79 | #
80 | # This special exception to the GPL applies to versions of the Autoconf
81 | # Macro released by the Autoconf Archive. When you make and distribute a
82 | # modified version of the Autoconf Macro, you may extend this special
83 | # exception to the GPL to apply to your modified version as well.
84 |
85 | #serial 18
86 |
87 | AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
88 | AC_DEFUN([AX_PTHREAD], [
89 | AC_REQUIRE([AC_CANONICAL_HOST])
90 | AC_LANG_PUSH([C])
91 | ax_pthread_ok=no
92 |
93 | # We used to check for pthread.h first, but this fails if pthread.h
94 | # requires special compiler flags (e.g. on True64 or Sequent).
95 | # It gets checked for in the link test anyway.
96 |
97 | # First of all, check if the user has set any of the PTHREAD_LIBS,
98 | # etcetera environment variables, and if threads linking works using
99 | # them:
100 | if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
101 | save_CFLAGS="$CFLAGS"
102 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
103 | save_LIBS="$LIBS"
104 | LIBS="$PTHREAD_LIBS $LIBS"
105 | AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
106 | AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes)
107 | AC_MSG_RESULT($ax_pthread_ok)
108 | if test x"$ax_pthread_ok" = xno; then
109 | PTHREAD_LIBS=""
110 | PTHREAD_CFLAGS=""
111 | fi
112 | LIBS="$save_LIBS"
113 | CFLAGS="$save_CFLAGS"
114 | fi
115 |
116 | # We must check for the threads library under a number of different
117 | # names; the ordering is very important because some systems
118 | # (e.g. DEC) have both -lpthread and -lpthreads, where one of the
119 | # libraries is broken (non-POSIX).
120 |
121 | # Create a list of thread flags to try. Items starting with a "-" are
122 | # C compiler flags, and other items are library names, except for "none"
123 | # which indicates that we try without any flags at all, and "pthread-config"
124 | # which is a program returning the flags for the Pth emulation library.
125 |
126 | ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
127 |
128 | # The ordering *is* (sometimes) important. Some notes on the
129 | # individual items follow:
130 |
131 | # pthreads: AIX (must check this before -lpthread)
132 | # none: in case threads are in libc; should be tried before -Kthread and
133 | # other compiler flags to prevent continual compiler warnings
134 | # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
135 | # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
136 | # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
137 | # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
138 | # -pthreads: Solaris/gcc
139 | # -mthreads: Mingw32/gcc, Lynx/gcc
140 | # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
141 | # doesn't hurt to check since this sometimes defines pthreads too;
142 | # also defines -D_REENTRANT)
143 | # ... -mt is also the pthreads flag for HP/aCC
144 | # pthread: Linux, etcetera
145 | # --thread-safe: KAI C++
146 | # pthread-config: use pthread-config program (for GNU Pth library)
147 |
148 | case ${host_os} in
149 | solaris*)
150 |
151 | # On Solaris (at least, for some versions), libc contains stubbed
152 | # (non-functional) versions of the pthreads routines, so link-based
153 | # tests will erroneously succeed. (We need to link with -pthreads/-mt/
154 | # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
155 | # a function called by this macro, so we could check for that, but
156 | # who knows whether they'll stub that too in a future libc.) So,
157 | # we'll just look for -pthreads and -lpthread first:
158 |
159 | ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
160 | ;;
161 |
162 | darwin*)
163 | ax_pthread_flags="-pthread $ax_pthread_flags"
164 | ;;
165 | esac
166 |
167 | if test x"$ax_pthread_ok" = xno; then
168 | for flag in $ax_pthread_flags; do
169 |
170 | case $flag in
171 | none)
172 | AC_MSG_CHECKING([whether pthreads work without any flags])
173 | ;;
174 |
175 | -*)
176 | AC_MSG_CHECKING([whether pthreads work with $flag])
177 | PTHREAD_CFLAGS="$flag"
178 | ;;
179 |
180 | pthread-config)
181 | AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no)
182 | if test x"$ax_pthread_config" = xno; then continue; fi
183 | PTHREAD_CFLAGS="`pthread-config --cflags`"
184 | PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
185 | ;;
186 |
187 | *)
188 | AC_MSG_CHECKING([for the pthreads library -l$flag])
189 | PTHREAD_LIBS="-l$flag"
190 | ;;
191 | esac
192 |
193 | save_LIBS="$LIBS"
194 | save_CFLAGS="$CFLAGS"
195 | LIBS="$PTHREAD_LIBS $LIBS"
196 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
197 |
198 | # Check for various functions. We must include pthread.h,
199 | # since some functions may be macros. (On the Sequent, we
200 | # need a special flag -Kthread to make this header compile.)
201 | # We check for pthread_join because it is in -lpthread on IRIX
202 | # while pthread_create is in libc. We check for pthread_attr_init
203 | # due to DEC craziness with -lpthreads. We check for
204 | # pthread_cleanup_push because it is one of the few pthread
205 | # functions on Solaris that doesn't have a non-functional libc stub.
206 | # We try pthread_create on general principles.
207 | AC_LINK_IFELSE([AC_LANG_PROGRAM([#include
208 | static void routine(void *a) { a = 0; }
209 | static void *start_routine(void *a) { return a; }],
210 | [pthread_t th; pthread_attr_t attr;
211 | pthread_create(&th, 0, start_routine, 0);
212 | pthread_join(th, 0);
213 | pthread_attr_init(&attr);
214 | pthread_cleanup_push(routine, 0);
215 | pthread_cleanup_pop(0) /* ; */])],
216 | [ax_pthread_ok=yes],
217 | [])
218 |
219 | LIBS="$save_LIBS"
220 | CFLAGS="$save_CFLAGS"
221 |
222 | AC_MSG_RESULT($ax_pthread_ok)
223 | if test "x$ax_pthread_ok" = xyes; then
224 | break;
225 | fi
226 |
227 | PTHREAD_LIBS=""
228 | PTHREAD_CFLAGS=""
229 | done
230 | fi
231 |
232 | # Various other checks:
233 | if test "x$ax_pthread_ok" = xyes; then
234 | save_LIBS="$LIBS"
235 | LIBS="$PTHREAD_LIBS $LIBS"
236 | save_CFLAGS="$CFLAGS"
237 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
238 |
239 | # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
240 | AC_MSG_CHECKING([for joinable pthread attribute])
241 | attr_name=unknown
242 | for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
243 | AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ],
244 | [int attr = $attr; return attr /* ; */])],
245 | [attr_name=$attr; break],
246 | [])
247 | done
248 | AC_MSG_RESULT($attr_name)
249 | if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
250 | AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
251 | [Define to necessary symbol if this constant
252 | uses a non-standard name on your system.])
253 | fi
254 |
255 | AC_MSG_CHECKING([if more special flags are required for pthreads])
256 | flag=no
257 | case ${host_os} in
258 | aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
259 | osf* | hpux*) flag="-D_REENTRANT";;
260 | solaris*)
261 | if test "$GCC" = "yes"; then
262 | flag="-D_REENTRANT"
263 | else
264 | flag="-mt -D_REENTRANT"
265 | fi
266 | ;;
267 | esac
268 | AC_MSG_RESULT(${flag})
269 | if test "x$flag" != xno; then
270 | PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
271 | fi
272 |
273 | AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
274 | ax_cv_PTHREAD_PRIO_INHERIT, [
275 | AC_LINK_IFELSE([
276 | AC_LANG_PROGRAM([[#include ]], [[int i = PTHREAD_PRIO_INHERIT;]])],
277 | [ax_cv_PTHREAD_PRIO_INHERIT=yes],
278 | [ax_cv_PTHREAD_PRIO_INHERIT=no])
279 | ])
280 | AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
281 | AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.]))
282 |
283 | LIBS="$save_LIBS"
284 | CFLAGS="$save_CFLAGS"
285 |
286 | # More AIX lossage: must compile with xlc_r or cc_r
287 | if test x"$GCC" != xyes; then
288 | AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
289 | else
290 | PTHREAD_CC=$CC
291 | fi
292 | else
293 | PTHREAD_CC="$CC"
294 | fi
295 |
296 | AC_SUBST(PTHREAD_LIBS)
297 | AC_SUBST(PTHREAD_CFLAGS)
298 | AC_SUBST(PTHREAD_CC)
299 |
300 | # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
301 | if test x"$ax_pthread_ok" = xyes; then
302 | ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
303 | :
304 | else
305 | ax_pthread_ok=no
306 | $2
307 | fi
308 | AC_LANG_POP
309 | ])dnl AX_PTHREAD
310 |
--------------------------------------------------------------------------------
/hidapi/m4/pkg.m4:
--------------------------------------------------------------------------------
1 | # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
2 | #
3 | # Copyright © 2004 Scott James Remnant .
4 | #
5 | # This program is free software; you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation; either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program; if not, write to the Free Software
17 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 | #
19 | # As a special exception to the GNU General Public License, if you
20 | # distribute this file as part of a program that contains a
21 | # configuration script generated by Autoconf, you may include it under
22 | # the same distribution terms that you use for the rest of that program.
23 |
24 | # PKG_PROG_PKG_CONFIG([MIN-VERSION])
25 | # ----------------------------------
26 | AC_DEFUN([PKG_PROG_PKG_CONFIG],
27 | [m4_pattern_forbid([^_?PKG_[A-Z_]+$])
28 | m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
29 | AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
30 | if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
31 | AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
32 | fi
33 | if test -n "$PKG_CONFIG"; then
34 | _pkg_min_version=m4_default([$1], [0.9.0])
35 | AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
36 | if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
37 | AC_MSG_RESULT([yes])
38 | else
39 | AC_MSG_RESULT([no])
40 | PKG_CONFIG=""
41 | fi
42 |
43 | fi[]dnl
44 | ])# PKG_PROG_PKG_CONFIG
45 |
46 | # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
47 | #
48 | # Check to see whether a particular set of modules exists. Similar
49 | # to PKG_CHECK_MODULES(), but does not set variables or print errors.
50 | #
51 | #
52 | # Similar to PKG_CHECK_MODULES, make sure that the first instance of
53 | # this or PKG_CHECK_MODULES is called, or make sure to call
54 | # PKG_CHECK_EXISTS manually
55 | # --------------------------------------------------------------
56 | AC_DEFUN([PKG_CHECK_EXISTS],
57 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
58 | if test -n "$PKG_CONFIG" && \
59 | AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
60 | m4_ifval([$2], [$2], [:])
61 | m4_ifvaln([$3], [else
62 | $3])dnl
63 | fi])
64 |
65 |
66 | # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
67 | # ---------------------------------------------
68 | m4_define([_PKG_CONFIG],
69 | [if test -n "$PKG_CONFIG"; then
70 | if test -n "$$1"; then
71 | pkg_cv_[]$1="$$1"
72 | else
73 | PKG_CHECK_EXISTS([$3],
74 | [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
75 | [pkg_failed=yes])
76 | fi
77 | else
78 | pkg_failed=untried
79 | fi[]dnl
80 | ])# _PKG_CONFIG
81 |
82 | # _PKG_SHORT_ERRORS_SUPPORTED
83 | # -----------------------------
84 | AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
85 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG])
86 | if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
87 | _pkg_short_errors_supported=yes
88 | else
89 | _pkg_short_errors_supported=no
90 | fi[]dnl
91 | ])# _PKG_SHORT_ERRORS_SUPPORTED
92 |
93 |
94 | # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
95 | # [ACTION-IF-NOT-FOUND])
96 | #
97 | #
98 | # Note that if there is a possibility the first call to
99 | # PKG_CHECK_MODULES might not happen, you should be sure to include an
100 | # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
101 | #
102 | #
103 | # --------------------------------------------------------------
104 | AC_DEFUN([PKG_CHECK_MODULES],
105 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
106 | AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
107 | AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
108 |
109 | pkg_failed=no
110 | AC_MSG_CHECKING([for $1])
111 |
112 | _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
113 | _PKG_CONFIG([$1][_LIBS], [libs], [$2])
114 |
115 | m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
116 | and $1[]_LIBS to avoid the need to call pkg-config.
117 | See the pkg-config man page for more details.])
118 |
119 | if test $pkg_failed = yes; then
120 | _PKG_SHORT_ERRORS_SUPPORTED
121 | if test $_pkg_short_errors_supported = yes; then
122 | $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
123 | else
124 | $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
125 | fi
126 | # Put the nasty error message in config.log where it belongs
127 | echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
128 |
129 | ifelse([$4], , [AC_MSG_ERROR(dnl
130 | [Package requirements ($2) were not met:
131 |
132 | $$1_PKG_ERRORS
133 |
134 | Consider adjusting the PKG_CONFIG_PATH environment variable if you
135 | installed software in a non-standard prefix.
136 |
137 | _PKG_TEXT
138 | ])],
139 | [AC_MSG_RESULT([no])
140 | $4])
141 | elif test $pkg_failed = untried; then
142 | ifelse([$4], , [AC_MSG_FAILURE(dnl
143 | [The pkg-config script could not be found or is too old. Make sure it
144 | is in your PATH or set the PKG_CONFIG environment variable to the full
145 | path to pkg-config.
146 |
147 | _PKG_TEXT
148 |
149 | To get pkg-config, see .])],
150 | [$4])
151 | else
152 | $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
153 | $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
154 | AC_MSG_RESULT([yes])
155 | ifelse([$3], , :, [$3])
156 | fi[]dnl
157 | ])# PKG_CHECK_MODULES
158 |
--------------------------------------------------------------------------------
/hidapi/mac/.gitignore:
--------------------------------------------------------------------------------
1 | Debug
2 | Release
3 | *.exp
4 | *.ilk
5 | *.lib
6 | *.suo
7 | *.vcproj.*
8 | *.ncb
9 | *.suo
10 | *.dll
11 | *.pdb
12 | *.o
13 | hidapi-hidtest
14 | .deps
15 | .libs
16 | *.la
17 | *.lo
18 |
--------------------------------------------------------------------------------
/hidapi/mac/Makefile-manual:
--------------------------------------------------------------------------------
1 | ###########################################
2 | # Simple Makefile for HIDAPI test program
3 | #
4 | # Alan Ott
5 | # Signal 11 Software
6 | # 2010-07-03
7 | ###########################################
8 |
9 | all: hidtest
10 |
11 | CC=gcc
12 | CXX=g++
13 | COBJS=hid.o ../hidtest/test.o
14 | OBJS=$(COBJS)
15 | CFLAGS+=-I../hidapi -Wall -g -c
16 | LIBS=-framework IOKit -framework CoreFoundation
17 |
18 |
19 | hidtest: $(OBJS)
20 | $(CC) -Wall -g $^ $(LIBS) -o hidtest
21 |
22 | $(COBJS): %.o: %.c
23 | $(CC) $(CFLAGS) $< -o $@
24 |
25 | $(CPPOBJS): %.o: %.cpp
26 | $(CXX) $(CFLAGS) $< -o $@
27 |
28 | clean:
29 | rm -f *.o hidtest $(CPPOBJS)
30 |
31 | .PHONY: clean
32 |
--------------------------------------------------------------------------------
/hidapi/mac/Makefile.am:
--------------------------------------------------------------------------------
1 | lib_LTLIBRARIES = libhidapi.la
2 | libhidapi_la_SOURCES = hid.c
3 | libhidapi_la_LDFLAGS = $(LTLDFLAGS)
4 | AM_CPPFLAGS = -I$(top_srcdir)/hidapi/
5 |
6 | hdrdir = $(includedir)/hidapi
7 | hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h
8 |
9 | EXTRA_DIST = Makefile-manual
10 |
--------------------------------------------------------------------------------
/hidapi/mac/hidtest:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erikmwerner/QJoyControl/0c6495329d13d62b42ef26271646a1393028e4e2/hidapi/mac/hidtest
--------------------------------------------------------------------------------
/hidapi/pc/.gitignore:
--------------------------------------------------------------------------------
1 | *.pc
2 |
--------------------------------------------------------------------------------
/hidapi/pc/hidapi-hidraw.pc.in:
--------------------------------------------------------------------------------
1 | prefix=@prefix@
2 | exec_prefix=@exec_prefix@
3 | libdir=@libdir@
4 | includedir=@includedir@
5 |
6 | Name: hidapi-hidraw
7 | Description: C Library for USB/Bluetooth HID device access from Linux, Mac OS X, FreeBSD, and Windows. This is the hidraw implementation.
8 | Version: @VERSION@
9 | Libs: -L${libdir} -lhidapi-hidraw
10 | Cflags: -I${includedir}/hidapi
11 |
--------------------------------------------------------------------------------
/hidapi/pc/hidapi-libusb.pc.in:
--------------------------------------------------------------------------------
1 | prefix=@prefix@
2 | exec_prefix=@exec_prefix@
3 | libdir=@libdir@
4 | includedir=@includedir@
5 |
6 | Name: hidapi-libusb
7 | Description: C Library for USB HID device access from Linux, Mac OS X, FreeBSD, and Windows. This is the libusb implementation.
8 | Version: @VERSION@
9 | Libs: -L${libdir} -lhidapi-libusb
10 | Cflags: -I${includedir}/hidapi
11 |
--------------------------------------------------------------------------------
/hidapi/pc/hidapi.pc.in:
--------------------------------------------------------------------------------
1 | prefix=@prefix@
2 | exec_prefix=@exec_prefix@
3 | libdir=@libdir@
4 | includedir=@includedir@
5 |
6 | Name: hidapi
7 | Description: C Library for USB/Bluetooth HID device access from Linux, Mac OS X, FreeBSD, and Windows.
8 | Version: @VERSION@
9 | Libs: -L${libdir} -lhidapi
10 | Cflags: -I${includedir}/hidapi
11 |
--------------------------------------------------------------------------------
/hidapi/testgui/.gitignore:
--------------------------------------------------------------------------------
1 | Debug
2 | Release
3 | *.exp
4 | *.ilk
5 | *.lib
6 | *.suo
7 | *.vcproj.*
8 | *.ncb
9 | *.suo
10 | *.dll
11 | *.pdb
12 | *.o
13 | hidapi-testgui
14 | hidapi-hidraw-testgui
15 | hidapi-libusb-testgui
16 | .deps
17 | .libs
18 | *.la
19 | *.lo
20 | TestGUI.app
21 |
--------------------------------------------------------------------------------
/hidapi/testgui/Makefile-manual:
--------------------------------------------------------------------------------
1 |
2 |
3 | OS=$(shell uname)
4 |
5 | ifeq ($(OS), Darwin)
6 | FILE=Makefile.mac
7 | endif
8 |
9 | ifneq (,$(findstring MINGW,$(OS)))
10 | FILE=Makefile.mingw
11 | endif
12 |
13 | ifeq ($(OS), Linux)
14 | FILE=Makefile.linux
15 | endif
16 |
17 | ifeq ($(OS), FreeBSD)
18 | FILE=Makefile.freebsd
19 | endif
20 |
21 | ifeq ($(FILE), )
22 | all:
23 | $(error Your platform ${OS} is not supported at this time.)
24 | endif
25 |
26 | include $(FILE)
27 |
--------------------------------------------------------------------------------
/hidapi/testgui/Makefile.am:
--------------------------------------------------------------------------------
1 |
2 | AM_CPPFLAGS = -I$(top_srcdir)/hidapi/ $(CFLAGS_TESTGUI)
3 |
4 | if OS_LINUX
5 | ## Linux
6 | bin_PROGRAMS = hidapi-hidraw-testgui hidapi-libusb-testgui
7 |
8 | hidapi_hidraw_testgui_SOURCES = test.cpp
9 | hidapi_hidraw_testgui_LDADD = $(top_builddir)/linux/libhidapi-hidraw.la $(LIBS_TESTGUI)
10 |
11 | hidapi_libusb_testgui_SOURCES = test.cpp
12 | hidapi_libusb_testgui_LDADD = $(top_builddir)/libusb/libhidapi-libusb.la $(LIBS_TESTGUI)
13 | else
14 | ## Other OS's
15 | bin_PROGRAMS = hidapi-testgui
16 |
17 | hidapi_testgui_SOURCES = test.cpp
18 | hidapi_testgui_LDADD = $(top_builddir)/$(backend)/libhidapi.la $(LIBS_TESTGUI)
19 | endif
20 |
21 | if OS_DARWIN
22 | hidapi_testgui_SOURCES = test.cpp mac_support_cocoa.m mac_support.h
23 | # Rules for copying the binary and its dependencies into the app bundle.
24 | TestGUI.app/Contents/MacOS/hidapi-testgui$(EXEEXT): hidapi-testgui$(EXEEXT)
25 | $(srcdir)/copy_to_bundle.sh
26 |
27 | all: all-am TestGUI.app/Contents/MacOS/hidapi-testgui$(EXEEXT)
28 |
29 | endif
30 |
31 | EXTRA_DIST = \
32 | copy_to_bundle.sh \
33 | Makefile-manual \
34 | Makefile.freebsd \
35 | Makefile.linux \
36 | Makefile.mac \
37 | Makefile.mingw \
38 | TestGUI.app.in \
39 | testgui.sln \
40 | testgui.vcproj
41 |
42 | distclean-local:
43 | rm -rf TestGUI.app
44 |
--------------------------------------------------------------------------------
/hidapi/testgui/Makefile.freebsd:
--------------------------------------------------------------------------------
1 | ###########################################
2 | # Simple Makefile for HIDAPI test program
3 | #
4 | # Alan Ott
5 | # Signal 11 Software
6 | # 2010-06-01
7 | ###########################################
8 |
9 | all: testgui
10 |
11 | CC=cc
12 | CXX=c++
13 | COBJS=../libusb/hid.o
14 | CPPOBJS=test.o
15 | OBJS=$(COBJS) $(CPPOBJS)
16 | CFLAGS=-I../hidapi -I/usr/local/include `fox-config --cflags` -Wall -g -c
17 | LDFLAGS= -L/usr/local/lib
18 | LIBS= -lusb -liconv `fox-config --libs` -pthread
19 |
20 |
21 | testgui: $(OBJS)
22 | $(CXX) -Wall -g $^ $(LDFLAGS) -o $@ $(LIBS)
23 |
24 | $(COBJS): %.o: %.c
25 | $(CC) $(CFLAGS) $< -o $@
26 |
27 | $(CPPOBJS): %.o: %.cpp
28 | $(CXX) $(CFLAGS) $< -o $@
29 |
30 | clean:
31 | rm *.o testgui
32 |
33 | .PHONY: clean
34 |
--------------------------------------------------------------------------------
/hidapi/testgui/Makefile.linux:
--------------------------------------------------------------------------------
1 | ###########################################
2 | # Simple Makefile for HIDAPI test program
3 | #
4 | # Alan Ott
5 | # Signal 11 Software
6 | # 2010-06-01
7 | ###########################################
8 |
9 | all: testgui
10 |
11 | CC=gcc
12 | CXX=g++
13 | COBJS=../libusb/hid.o
14 | CPPOBJS=test.o
15 | OBJS=$(COBJS) $(CPPOBJS)
16 | CFLAGS=-I../hidapi -Wall -g -c `fox-config --cflags` `pkg-config libusb-1.0 --cflags`
17 | LIBS=-ludev -lrt -lpthread `fox-config --libs` `pkg-config libusb-1.0 --libs`
18 |
19 |
20 | testgui: $(OBJS)
21 | g++ -Wall -g $^ $(LIBS) -o testgui
22 |
23 | $(COBJS): %.o: %.c
24 | $(CC) $(CFLAGS) $< -o $@
25 |
26 | $(CPPOBJS): %.o: %.cpp
27 | $(CXX) $(CFLAGS) $< -o $@
28 |
29 | clean:
30 | rm *.o testgui
31 |
32 | .PHONY: clean
33 |
--------------------------------------------------------------------------------
/hidapi/testgui/Makefile.mac:
--------------------------------------------------------------------------------
1 | ###########################################
2 | # Simple Makefile for HIDAPI test program
3 | #
4 | # Alan Ott
5 | # Signal 11 Software
6 | # 2010-07-03
7 | ###########################################
8 |
9 | all: hidapi-testgui
10 |
11 | CC=gcc
12 | CXX=g++
13 | COBJS=../mac/hid.o
14 | CPPOBJS=test.o
15 | OBJCOBJS=mac_support_cocoa.o
16 | OBJS=$(COBJS) $(CPPOBJS) $(OBJCOBJS)
17 | CFLAGS=-I../hidapi -Wall -g -c `fox-config --cflags`
18 | LDFLAGS=-L/usr/X11R6/lib
19 | LIBS=`fox-config --libs` -framework IOKit -framework CoreFoundation -framework Cocoa
20 |
21 |
22 | hidapi-testgui: $(OBJS) TestGUI.app
23 | g++ -Wall -g $(OBJS) $(LIBS) $(LDFLAGS) -o hidapi-testgui
24 | ./copy_to_bundle.sh
25 | #cp TestGUI.app/Contents/MacOS/hidapi-testgui TestGUI.app/Contents/MacOS/tg
26 | #cp start.sh TestGUI.app/Contents/MacOS/hidapi-testgui
27 |
28 | $(COBJS): %.o: %.c
29 | $(CC) $(CFLAGS) $< -o $@
30 |
31 | $(CPPOBJS): %.o: %.cpp
32 | $(CXX) $(CFLAGS) $< -o $@
33 |
34 | $(OBJCOBJS): %.o: %.m
35 | $(CXX) $(CFLAGS) -x objective-c++ $< -o $@
36 |
37 | TestGUI.app: TestGUI.app.in
38 | rm -Rf TestGUI.app
39 | mkdir -p TestGUI.app
40 | cp -R TestGUI.app.in/ TestGUI.app
41 |
42 | clean:
43 | rm -f $(OBJS) hidapi-testgui
44 | rm -Rf TestGUI.app
45 |
46 | .PHONY: clean
47 |
--------------------------------------------------------------------------------
/hidapi/testgui/Makefile.mingw:
--------------------------------------------------------------------------------
1 | ###########################################
2 | # Simple Makefile for HIDAPI test program
3 | #
4 | # Alan Ott
5 | # Signal 11 Software
6 | # 2010-06-01
7 | ###########################################
8 |
9 | all: hidapi-testgui
10 |
11 | CC=gcc
12 | CXX=g++
13 | COBJS=../windows/hid.o
14 | CPPOBJS=test.o
15 | OBJS=$(COBJS) $(CPPOBJS)
16 | CFLAGS=-I../hidapi -I../../hidapi-externals/fox/include -g -c
17 | LIBS= -mwindows -lsetupapi -L../../hidapi-externals/fox/lib -Wl,-Bstatic -lFOX-1.6 -Wl,-Bdynamic -lgdi32 -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lkernel32
18 |
19 |
20 | hidapi-testgui: $(OBJS)
21 | g++ -g $^ $(LIBS) -o hidapi-testgui
22 |
23 | $(COBJS): %.o: %.c
24 | $(CC) $(CFLAGS) $< -o $@
25 |
26 | $(CPPOBJS): %.o: %.cpp
27 | $(CXX) $(CFLAGS) $< -o $@
28 |
29 | clean:
30 | rm -f *.o hidapi-testgui.exe
31 |
32 | .PHONY: clean
33 |
--------------------------------------------------------------------------------
/hidapi/testgui/TestGUI.app.in/Contents/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleDisplayName
8 |
9 | CFBundleExecutable
10 | hidapi-testgui
11 | CFBundleIconFile
12 | Signal11.icns
13 | CFBundleIdentifier
14 | us.signal11.hidtestgui
15 | CFBundleInfoDictionaryVersion
16 | 6.0
17 | CFBundleName
18 | testgui
19 | CFBundlePackageType
20 | APPL
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.0
25 | CSResourcesFileMapped
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/hidapi/testgui/TestGUI.app.in/Contents/PkgInfo:
--------------------------------------------------------------------------------
1 | APPL????
--------------------------------------------------------------------------------
/hidapi/testgui/TestGUI.app.in/Contents/Resources/English.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erikmwerner/QJoyControl/0c6495329d13d62b42ef26271646a1393028e4e2/hidapi/testgui/TestGUI.app.in/Contents/Resources/English.lproj/InfoPlist.strings
--------------------------------------------------------------------------------
/hidapi/testgui/TestGUI.app.in/Contents/Resources/Signal11.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erikmwerner/QJoyControl/0c6495329d13d62b42ef26271646a1393028e4e2/hidapi/testgui/TestGUI.app.in/Contents/Resources/Signal11.icns
--------------------------------------------------------------------------------
/hidapi/testgui/copy_to_bundle.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #### Configuration:
4 | # The name of the executable. It is assumed
5 | # that it is in the current working directory.
6 | EXE_NAME=hidapi-testgui
7 | # Path to the executable directory inside the bundle.
8 | # This must be an absolute path, so use $PWD.
9 | EXEPATH=$PWD/TestGUI.app/Contents/MacOS
10 | # Libraries to explicitly bundle, even though they
11 | # may not be in /opt/local. One per line. These
12 | # are used with grep, so only a portion of the name
13 | # is required. eg: libFOX, libz, etc.
14 | LIBS_TO_BUNDLE=libFOX
15 |
16 |
17 | function copydeps {
18 | local file=$1
19 | # echo "Copying deps for $file...."
20 | local BASE_OF_EXE=`basename $file`
21 |
22 | # A will contain the dependencies of this library
23 | local A=`otool -LX $file |cut -f 1 -d " "`
24 | local i
25 | for i in $A; do
26 | local BASE=`basename $i`
27 |
28 | # See if it's a lib we specifically want to bundle
29 | local bundle_this_lib=0
30 | local j
31 | for j in $LIBS_TO_BUNDLE; do
32 | echo $i |grep -q $j
33 | if [ $? -eq 0 ]; then
34 | bundle_this_lib=1
35 | echo "bundling $i because it's in the list."
36 | break;
37 | fi
38 | done
39 |
40 | # See if it's in /opt/local. Bundle all in /opt/local
41 | local isOptLocal=0
42 | echo $i |grep -q /opt/local
43 | if [ $? -eq 0 ]; then
44 | isOptLocal=1
45 | echo "bundling $i because it's in /opt/local."
46 | fi
47 |
48 | # Bundle the library
49 | if [ $isOptLocal -ne 0 ] || [ $bundle_this_lib -ne 0 ]; then
50 |
51 | # Copy the file into the bundle if it exists.
52 | if [ -f $EXEPATH/$BASE ]; then
53 | z=0
54 | else
55 | cp $i $EXEPATH
56 | chmod 755 $EXEPATH/$BASE
57 | fi
58 |
59 |
60 | # echo "$BASE_OF_EXE depends on $BASE"
61 |
62 | # Fix the paths using install_name_tool and then
63 | # call this function recursively for each dependency
64 | # of this library.
65 | if [ $BASE_OF_EXE != $BASE ]; then
66 |
67 | # Fix the paths
68 | install_name_tool -id @executable_path/$BASE $EXEPATH/$BASE
69 | install_name_tool -change $i @executable_path/$BASE $EXEPATH/$BASE_OF_EXE
70 |
71 | # Call this function (recursive) on
72 | # on each dependency of this library.
73 | copydeps $EXEPATH/$BASE
74 | fi
75 | fi
76 | done
77 | }
78 |
79 | rm -f $EXEPATH/*
80 |
81 | # Copy the binary into the bundle. Use ../libtool to do this if it's
82 | # available because if $EXE_NAME was built with autotools, it will be
83 | # necessary. If ../libtool not available, just use cp to do the copy, but
84 | # only if $EXE_NAME is a binary.
85 | if [ -x ../libtool ]; then
86 | ../libtool --mode=install cp $EXE_NAME $EXEPATH
87 | else
88 | file -bI $EXE_NAME |grep binary
89 | if [ $? -ne 0 ]; then
90 | echo "There is no ../libtool and $EXE_NAME is not a binary."
91 | echo "I'm not sure what to do."
92 | exit 1
93 | else
94 | cp $EXE_NAME $EXEPATH
95 | fi
96 | fi
97 | copydeps $EXEPATH/$EXE_NAME
98 |
--------------------------------------------------------------------------------
/hidapi/testgui/mac_support.h:
--------------------------------------------------------------------------------
1 | /*******************************
2 | Mac support for HID Test GUI
3 |
4 | Alan Ott
5 | Signal 11 Software
6 |
7 | *******************************/
8 |
9 | #ifndef MAC_SUPPORT_H__
10 | #define MAC_SUPPORT_H__
11 |
12 | extern "C" {
13 | void init_apple_message_system();
14 | void check_apple_events();
15 | }
16 |
17 | #endif
18 |
--------------------------------------------------------------------------------
/hidapi/testgui/mac_support_cocoa.m:
--------------------------------------------------------------------------------
1 | /*******************************
2 | Mac support for HID Test GUI
3 |
4 | Alan Ott
5 | Signal 11 Software
6 | *******************************/
7 |
8 | #include
9 | #import
10 |
11 | #ifndef MAC_OS_X_VERSION_10_12
12 | #define MAC_OS_X_VERSION_10_12 101200
13 | #endif
14 |
15 | // macOS 10.12 deprecated NSAnyEventMask in favor of NSEventMaskAny
16 | #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
17 | #define NSEventMaskAny NSAnyEventMask
18 | #endif
19 |
20 | extern FXMainWindow *g_main_window;
21 |
22 |
23 | @interface MyAppDelegate : NSObject
24 | {
25 | }
26 | @end
27 |
28 | @implementation MyAppDelegate
29 | - (void) applicationWillBecomeActive:(NSNotification*)notif
30 | {
31 | printf("WillBecomeActive\n");
32 | g_main_window->show();
33 |
34 | }
35 |
36 | - (void) applicationWillTerminate:(NSNotification*)notif
37 | {
38 | /* Doesn't get called. Not sure why */
39 | printf("WillTerminate\n");
40 | FXApp::instance()->exit();
41 | }
42 |
43 | - (NSApplicationTerminateReply) applicationShouldTerminate:(NSApplication*)sender
44 | {
45 | /* Doesn't get called. Not sure why */
46 | printf("ShouldTerminate\n");
47 | return YES;
48 | }
49 |
50 | - (void) applicationWillHide:(NSNotification*)notif
51 | {
52 | printf("WillHide\n");
53 | g_main_window->hide();
54 | }
55 |
56 | - (void) handleQuitEvent:(NSAppleEventDescriptor*)event withReplyEvent:(NSAppleEventDescriptor*)replyEvent
57 | {
58 | printf("QuitEvent\n");
59 | FXApp::instance()->exit();
60 | }
61 |
62 | @end
63 |
64 | extern "C" {
65 |
66 | void
67 | init_apple_message_system()
68 | {
69 | static MyAppDelegate *d = [MyAppDelegate new];
70 |
71 | [[NSApplication sharedApplication] setDelegate:d];
72 |
73 | /* Register for Apple Events. */
74 | /* This is from
75 | http://stackoverflow.com/questions/1768497/application-exit-event */
76 | NSAppleEventManager *aem = [NSAppleEventManager sharedAppleEventManager];
77 | [aem setEventHandler:d
78 | andSelector:@selector(handleQuitEvent:withReplyEvent:)
79 | forEventClass:kCoreEventClass andEventID:kAEQuitApplication];
80 | }
81 |
82 | void
83 | check_apple_events()
84 | {
85 | NSApplication *app = [NSApplication sharedApplication];
86 |
87 | NSAutoreleasePool *pool = [NSAutoreleasePool new];
88 | while (1) {
89 | NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
90 | untilDate:nil
91 | inMode:NSDefaultRunLoopMode
92 | dequeue:YES];
93 | if (event == NULL)
94 | break;
95 | else {
96 | //printf("Event happened: Type: %d\n", event->_type);
97 | [app sendEvent: event];
98 | }
99 | }
100 | [pool release];
101 | }
102 |
103 | } /* extern "C" */
104 |
--------------------------------------------------------------------------------
/hidapi/testgui/test.cpp:
--------------------------------------------------------------------------------
1 | /*******************************************************
2 | Demo Program for HIDAPI
3 |
4 | Alan Ott
5 | Signal 11 Software
6 |
7 | 2010-07-20
8 |
9 | Copyright 2010, All Rights Reserved
10 |
11 | This contents of this file may be used by anyone
12 | for any reason without any conditions and may be
13 | used as a starting point for your own applications
14 | which use HIDAPI.
15 | ********************************************************/
16 |
17 |
18 | #include
19 |
20 | #include "hidapi.h"
21 | #include "mac_support.h"
22 | #include
23 | #include
24 | #include
25 |
26 | #ifdef _WIN32
27 | // Thanks Microsoft, but I know how to use strncpy().
28 | #pragma warning(disable:4996)
29 | #endif
30 |
31 | class MainWindow : public FXMainWindow {
32 | FXDECLARE(MainWindow)
33 |
34 | public:
35 | enum {
36 | ID_FIRST = FXMainWindow::ID_LAST,
37 | ID_CONNECT,
38 | ID_DISCONNECT,
39 | ID_RESCAN,
40 | ID_SEND_OUTPUT_REPORT,
41 | ID_SEND_FEATURE_REPORT,
42 | ID_GET_FEATURE_REPORT,
43 | ID_CLEAR,
44 | ID_TIMER,
45 | ID_MAC_TIMER,
46 | ID_LAST,
47 | };
48 |
49 | private:
50 | FXList *device_list;
51 | FXButton *connect_button;
52 | FXButton *disconnect_button;
53 | FXButton *rescan_button;
54 | FXButton *output_button;
55 | FXLabel *connected_label;
56 | FXTextField *output_text;
57 | FXTextField *output_len;
58 | FXButton *feature_button;
59 | FXButton *get_feature_button;
60 | FXTextField *feature_text;
61 | FXTextField *feature_len;
62 | FXTextField *get_feature_text;
63 | FXText *input_text;
64 | FXFont *title_font;
65 |
66 | struct hid_device_info *devices;
67 | hid_device *connected_device;
68 | size_t getDataFromTextField(FXTextField *tf, char *buf, size_t len);
69 | int getLengthFromTextField(FXTextField *tf);
70 |
71 |
72 | protected:
73 | MainWindow() {};
74 | public:
75 | MainWindow(FXApp *a);
76 | ~MainWindow();
77 | virtual void create();
78 |
79 | long onConnect(FXObject *sender, FXSelector sel, void *ptr);
80 | long onDisconnect(FXObject *sender, FXSelector sel, void *ptr);
81 | long onRescan(FXObject *sender, FXSelector sel, void *ptr);
82 | long onSendOutputReport(FXObject *sender, FXSelector sel, void *ptr);
83 | long onSendFeatureReport(FXObject *sender, FXSelector sel, void *ptr);
84 | long onGetFeatureReport(FXObject *sender, FXSelector sel, void *ptr);
85 | long onClear(FXObject *sender, FXSelector sel, void *ptr);
86 | long onTimeout(FXObject *sender, FXSelector sel, void *ptr);
87 | long onMacTimeout(FXObject *sender, FXSelector sel, void *ptr);
88 | };
89 |
90 | // FOX 1.7 changes the timeouts to all be nanoseconds.
91 | // Fox 1.6 had all timeouts as milliseconds.
92 | #if (FOX_MINOR >= 7)
93 | const int timeout_scalar = 1000*1000;
94 | #else
95 | const int timeout_scalar = 1;
96 | #endif
97 |
98 | FXMainWindow *g_main_window;
99 |
100 |
101 | FXDEFMAP(MainWindow) MainWindowMap [] = {
102 | FXMAPFUNC(SEL_COMMAND, MainWindow::ID_CONNECT, MainWindow::onConnect ),
103 | FXMAPFUNC(SEL_COMMAND, MainWindow::ID_DISCONNECT, MainWindow::onDisconnect ),
104 | FXMAPFUNC(SEL_COMMAND, MainWindow::ID_RESCAN, MainWindow::onRescan ),
105 | FXMAPFUNC(SEL_COMMAND, MainWindow::ID_SEND_OUTPUT_REPORT, MainWindow::onSendOutputReport ),
106 | FXMAPFUNC(SEL_COMMAND, MainWindow::ID_SEND_FEATURE_REPORT, MainWindow::onSendFeatureReport ),
107 | FXMAPFUNC(SEL_COMMAND, MainWindow::ID_GET_FEATURE_REPORT, MainWindow::onGetFeatureReport ),
108 | FXMAPFUNC(SEL_COMMAND, MainWindow::ID_CLEAR, MainWindow::onClear ),
109 | FXMAPFUNC(SEL_TIMEOUT, MainWindow::ID_TIMER, MainWindow::onTimeout ),
110 | FXMAPFUNC(SEL_TIMEOUT, MainWindow::ID_MAC_TIMER, MainWindow::onMacTimeout ),
111 | };
112 |
113 | FXIMPLEMENT(MainWindow, FXMainWindow, MainWindowMap, ARRAYNUMBER(MainWindowMap));
114 |
115 | MainWindow::MainWindow(FXApp *app)
116 | : FXMainWindow(app, "HIDAPI Test Application", NULL, NULL, DECOR_ALL, 200,100, 425,700)
117 | {
118 | devices = NULL;
119 | connected_device = NULL;
120 |
121 | FXVerticalFrame *vf = new FXVerticalFrame(this, LAYOUT_FILL_Y|LAYOUT_FILL_X);
122 |
123 | FXLabel *label = new FXLabel(vf, "HIDAPI Test Tool");
124 | title_font = new FXFont(getApp(), "Arial", 14, FXFont::Bold);
125 | label->setFont(title_font);
126 |
127 | new FXLabel(vf,
128 | "Select a device and press Connect.", NULL, JUSTIFY_LEFT);
129 | new FXLabel(vf,
130 | "Output data bytes can be entered in the Output section, \n"
131 | "separated by space, comma or brackets. Data starting with 0x\n"
132 | "is treated as hex. Data beginning with a 0 is treated as \n"
133 | "octal. All other data is treated as decimal.", NULL, JUSTIFY_LEFT);
134 | new FXLabel(vf,
135 | "Data received from the device appears in the Input section.",
136 | NULL, JUSTIFY_LEFT);
137 | new FXLabel(vf,
138 | "Optionally, a report length may be specified. Extra bytes are\n"
139 | "padded with zeros. If no length is specified, the length is \n"
140 | "inferred from the data.",
141 | NULL, JUSTIFY_LEFT);
142 | new FXLabel(vf, "");
143 |
144 | // Device List and Connect/Disconnect buttons
145 | FXHorizontalFrame *hf = new FXHorizontalFrame(vf, LAYOUT_FILL_X);
146 | //device_list = new FXList(new FXHorizontalFrame(hf,FRAME_SUNKEN|FRAME_THICK, 0,0,0,0, 0,0,0,0), NULL, 0, LISTBOX_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, 0,0,300,200);
147 | device_list = new FXList(new FXHorizontalFrame(hf,FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,0,0, 0,0,0,0), NULL, 0, LISTBOX_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,300,200);
148 | FXVerticalFrame *buttonVF = new FXVerticalFrame(hf);
149 | connect_button = new FXButton(buttonVF, "Connect", NULL, this, ID_CONNECT, BUTTON_NORMAL|LAYOUT_FILL_X);
150 | disconnect_button = new FXButton(buttonVF, "Disconnect", NULL, this, ID_DISCONNECT, BUTTON_NORMAL|LAYOUT_FILL_X);
151 | disconnect_button->disable();
152 | rescan_button = new FXButton(buttonVF, "Re-Scan devices", NULL, this, ID_RESCAN, BUTTON_NORMAL|LAYOUT_FILL_X);
153 | new FXHorizontalFrame(buttonVF, 0, 0,0,0,0, 0,0,50,0);
154 |
155 | connected_label = new FXLabel(vf, "Disconnected");
156 |
157 | new FXHorizontalFrame(vf);
158 |
159 | // Output Group Box
160 | FXGroupBox *gb = new FXGroupBox(vf, "Output", FRAME_GROOVE|LAYOUT_FILL_X);
161 | FXMatrix *matrix = new FXMatrix(gb, 3, MATRIX_BY_COLUMNS|LAYOUT_FILL_X);
162 | new FXLabel(matrix, "Data");
163 | new FXLabel(matrix, "Length");
164 | new FXLabel(matrix, "");
165 |
166 | //hf = new FXHorizontalFrame(gb, LAYOUT_FILL_X);
167 | output_text = new FXTextField(matrix, 30, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
168 | output_text->setText("1 0x81 0");
169 | output_len = new FXTextField(matrix, 5, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
170 | output_button = new FXButton(matrix, "Send Output Report", NULL, this, ID_SEND_OUTPUT_REPORT, BUTTON_NORMAL|LAYOUT_FILL_X);
171 | output_button->disable();
172 | //new FXHorizontalFrame(matrix, LAYOUT_FILL_X);
173 |
174 | //hf = new FXHorizontalFrame(gb, LAYOUT_FILL_X);
175 | feature_text = new FXTextField(matrix, 30, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
176 | feature_len = new FXTextField(matrix, 5, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
177 | feature_button = new FXButton(matrix, "Send Feature Report", NULL, this, ID_SEND_FEATURE_REPORT, BUTTON_NORMAL|LAYOUT_FILL_X);
178 | feature_button->disable();
179 |
180 | get_feature_text = new FXTextField(matrix, 30, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
181 | new FXWindow(matrix);
182 | get_feature_button = new FXButton(matrix, "Get Feature Report", NULL, this, ID_GET_FEATURE_REPORT, BUTTON_NORMAL|LAYOUT_FILL_X);
183 | get_feature_button->disable();
184 |
185 |
186 | // Input Group Box
187 | gb = new FXGroupBox(vf, "Input", FRAME_GROOVE|LAYOUT_FILL_X|LAYOUT_FILL_Y);
188 | FXVerticalFrame *innerVF = new FXVerticalFrame(gb, LAYOUT_FILL_X|LAYOUT_FILL_Y);
189 | input_text = new FXText(new FXHorizontalFrame(innerVF,LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK, 0,0,0,0, 0,0,0,0), NULL, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y);
190 | input_text->setEditable(false);
191 | new FXButton(innerVF, "Clear", NULL, this, ID_CLEAR, BUTTON_NORMAL|LAYOUT_RIGHT);
192 |
193 |
194 | }
195 |
196 | MainWindow::~MainWindow()
197 | {
198 | if (connected_device)
199 | hid_close(connected_device);
200 | hid_exit();
201 | delete title_font;
202 | }
203 |
204 | void
205 | MainWindow::create()
206 | {
207 | FXMainWindow::create();
208 | show();
209 |
210 | onRescan(NULL, 0, NULL);
211 |
212 |
213 | #ifdef __APPLE__
214 | init_apple_message_system();
215 | #endif
216 |
217 | getApp()->addTimeout(this, ID_MAC_TIMER,
218 | 50 * timeout_scalar /*50ms*/);
219 | }
220 |
221 | long
222 | MainWindow::onConnect(FXObject *sender, FXSelector sel, void *ptr)
223 | {
224 | if (connected_device != NULL)
225 | return 1;
226 |
227 | FXint cur_item = device_list->getCurrentItem();
228 | if (cur_item < 0)
229 | return -1;
230 | FXListItem *item = device_list->getItem(cur_item);
231 | if (!item)
232 | return -1;
233 | struct hid_device_info *device_info = (struct hid_device_info*) item->getData();
234 | if (!device_info)
235 | return -1;
236 |
237 | connected_device = hid_open_path(device_info->path);
238 |
239 | if (!connected_device) {
240 | FXMessageBox::error(this, MBOX_OK, "Device Error", "Unable To Connect to Device");
241 | return -1;
242 | }
243 |
244 | hid_set_nonblocking(connected_device, 1);
245 |
246 | getApp()->addTimeout(this, ID_TIMER,
247 | 5 * timeout_scalar /*5ms*/);
248 |
249 | FXString s;
250 | s.format("Connected to: %04hx:%04hx -", device_info->vendor_id, device_info->product_id);
251 | s += FXString(" ") + device_info->manufacturer_string;
252 | s += FXString(" ") + device_info->product_string;
253 | connected_label->setText(s);
254 | output_button->enable();
255 | feature_button->enable();
256 | get_feature_button->enable();
257 | connect_button->disable();
258 | disconnect_button->enable();
259 | input_text->setText("");
260 |
261 |
262 | return 1;
263 | }
264 |
265 | long
266 | MainWindow::onDisconnect(FXObject *sender, FXSelector sel, void *ptr)
267 | {
268 | hid_close(connected_device);
269 | connected_device = NULL;
270 | connected_label->setText("Disconnected");
271 | output_button->disable();
272 | feature_button->disable();
273 | get_feature_button->disable();
274 | connect_button->enable();
275 | disconnect_button->disable();
276 |
277 | getApp()->removeTimeout(this, ID_TIMER);
278 |
279 | return 1;
280 | }
281 |
282 | long
283 | MainWindow::onRescan(FXObject *sender, FXSelector sel, void *ptr)
284 | {
285 | struct hid_device_info *cur_dev;
286 |
287 | device_list->clearItems();
288 |
289 | // List the Devices
290 | hid_free_enumeration(devices);
291 | devices = hid_enumerate(0x0, 0x0);
292 | cur_dev = devices;
293 | while (cur_dev) {
294 | // Add it to the List Box.
295 | FXString s;
296 | FXString usage_str;
297 | s.format("%04hx:%04hx -", cur_dev->vendor_id, cur_dev->product_id);
298 | s += FXString(" ") + cur_dev->manufacturer_string;
299 | s += FXString(" ") + cur_dev->product_string;
300 | usage_str.format(" (usage: %04hx:%04hx) ", cur_dev->usage_page, cur_dev->usage);
301 | s += usage_str;
302 | FXListItem *li = new FXListItem(s, NULL, cur_dev);
303 | device_list->appendItem(li);
304 |
305 | cur_dev = cur_dev->next;
306 | }
307 |
308 | if (device_list->getNumItems() == 0)
309 | device_list->appendItem("*** No Devices Connected ***");
310 | else {
311 | device_list->selectItem(0);
312 | }
313 |
314 | return 1;
315 | }
316 |
317 | size_t
318 | MainWindow::getDataFromTextField(FXTextField *tf, char *buf, size_t len)
319 | {
320 | const char *delim = " ,{}\t\r\n";
321 | FXString data = tf->getText();
322 | const FXchar *d = data.text();
323 | size_t i = 0;
324 |
325 | // Copy the string from the GUI.
326 | size_t sz = strlen(d);
327 | char *str = (char*) malloc(sz+1);
328 | strcpy(str, d);
329 |
330 | // For each token in the string, parse and store in buf[].
331 | char *token = strtok(str, delim);
332 | while (token) {
333 | char *endptr;
334 | long int val = strtol(token, &endptr, 0);
335 | buf[i++] = val;
336 | token = strtok(NULL, delim);
337 | }
338 |
339 | free(str);
340 | return i;
341 | }
342 |
343 | /* getLengthFromTextField()
344 | Returns length:
345 | 0: empty text field
346 | >0: valid length
347 | -1: invalid length */
348 | int
349 | MainWindow::getLengthFromTextField(FXTextField *tf)
350 | {
351 | long int len;
352 | FXString str = tf->getText();
353 | size_t sz = str.length();
354 |
355 | if (sz > 0) {
356 | char *endptr;
357 | len = strtol(str.text(), &endptr, 0);
358 | if (endptr != str.text() && *endptr == '\0') {
359 | if (len <= 0) {
360 | FXMessageBox::error(this, MBOX_OK, "Invalid length", "Enter a length greater than zero.");
361 | return -1;
362 | }
363 | return len;
364 | }
365 | else
366 | return -1;
367 | }
368 |
369 | return 0;
370 | }
371 |
372 | long
373 | MainWindow::onSendOutputReport(FXObject *sender, FXSelector sel, void *ptr)
374 | {
375 | char buf[256];
376 | size_t data_len, len;
377 | int textfield_len;
378 |
379 | memset(buf, 0x0, sizeof(buf));
380 | textfield_len = getLengthFromTextField(output_len);
381 | data_len = getDataFromTextField(output_text, buf, sizeof(buf));
382 |
383 | if (textfield_len < 0) {
384 | FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is invalid. Please enter a number in hex, octal, or decimal.");
385 | return 1;
386 | }
387 |
388 | if (textfield_len > sizeof(buf)) {
389 | FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is too long.");
390 | return 1;
391 | }
392 |
393 | len = (textfield_len)? textfield_len: data_len;
394 |
395 | int res = hid_write(connected_device, (const unsigned char*)buf, len);
396 | if (res < 0) {
397 | FXMessageBox::error(this, MBOX_OK, "Error Writing", "Could not write to device. Error reported was: %ls", hid_error(connected_device));
398 | }
399 |
400 | return 1;
401 | }
402 |
403 | long
404 | MainWindow::onSendFeatureReport(FXObject *sender, FXSelector sel, void *ptr)
405 | {
406 | char buf[256];
407 | size_t data_len, len;
408 | int textfield_len;
409 |
410 | memset(buf, 0x0, sizeof(buf));
411 | textfield_len = getLengthFromTextField(feature_len);
412 | data_len = getDataFromTextField(feature_text, buf, sizeof(buf));
413 |
414 | if (textfield_len < 0) {
415 | FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is invalid. Please enter a number in hex, octal, or decimal.");
416 | return 1;
417 | }
418 |
419 | if (textfield_len > sizeof(buf)) {
420 | FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is too long.");
421 | return 1;
422 | }
423 |
424 | len = (textfield_len)? textfield_len: data_len;
425 |
426 | int res = hid_send_feature_report(connected_device, (const unsigned char*)buf, len);
427 | if (res < 0) {
428 | FXMessageBox::error(this, MBOX_OK, "Error Writing", "Could not send feature report to device. Error reported was: %ls", hid_error(connected_device));
429 | }
430 |
431 | return 1;
432 | }
433 |
434 | long
435 | MainWindow::onGetFeatureReport(FXObject *sender, FXSelector sel, void *ptr)
436 | {
437 | char buf[256];
438 | size_t len;
439 |
440 | memset(buf, 0x0, sizeof(buf));
441 | len = getDataFromTextField(get_feature_text, buf, sizeof(buf));
442 |
443 | if (len != 1) {
444 | FXMessageBox::error(this, MBOX_OK, "Too many numbers", "Enter only a single report number in the text field");
445 | }
446 |
447 | int res = hid_get_feature_report(connected_device, (unsigned char*)buf, sizeof(buf));
448 | if (res < 0) {
449 | FXMessageBox::error(this, MBOX_OK, "Error Getting Report", "Could not get feature report from device. Error reported was: %ls", hid_error(connected_device));
450 | }
451 |
452 | if (res > 0) {
453 | FXString s;
454 | s.format("Returned Feature Report. %d bytes:\n", res);
455 | for (int i = 0; i < res; i++) {
456 | FXString t;
457 | t.format("%02hhx ", buf[i]);
458 | s += t;
459 | if ((i+1) % 4 == 0)
460 | s += " ";
461 | if ((i+1) % 16 == 0)
462 | s += "\n";
463 | }
464 | s += "\n";
465 | input_text->appendText(s);
466 | input_text->setBottomLine(INT_MAX);
467 | }
468 |
469 | return 1;
470 | }
471 |
472 | long
473 | MainWindow::onClear(FXObject *sender, FXSelector sel, void *ptr)
474 | {
475 | input_text->setText("");
476 | return 1;
477 | }
478 |
479 | long
480 | MainWindow::onTimeout(FXObject *sender, FXSelector sel, void *ptr)
481 | {
482 | unsigned char buf[256];
483 | int res = hid_read(connected_device, buf, sizeof(buf));
484 |
485 | if (res > 0) {
486 | FXString s;
487 | s.format("Received %d bytes:\n", res);
488 | for (int i = 0; i < res; i++) {
489 | FXString t;
490 | t.format("%02hhx ", buf[i]);
491 | s += t;
492 | if ((i+1) % 4 == 0)
493 | s += " ";
494 | if ((i+1) % 16 == 0)
495 | s += "\n";
496 | }
497 | s += "\n";
498 | input_text->appendText(s);
499 | input_text->setBottomLine(INT_MAX);
500 | }
501 | if (res < 0) {
502 | input_text->appendText("hid_read() returned error\n");
503 | input_text->setBottomLine(INT_MAX);
504 | }
505 |
506 | getApp()->addTimeout(this, ID_TIMER,
507 | 5 * timeout_scalar /*5ms*/);
508 | return 1;
509 | }
510 |
511 | long
512 | MainWindow::onMacTimeout(FXObject *sender, FXSelector sel, void *ptr)
513 | {
514 | #ifdef __APPLE__
515 | check_apple_events();
516 |
517 | getApp()->addTimeout(this, ID_MAC_TIMER,
518 | 50 * timeout_scalar /*50ms*/);
519 | #endif
520 |
521 | return 1;
522 | }
523 |
524 | int main(int argc, char **argv)
525 | {
526 | FXApp app("HIDAPI Test Application", "Signal 11 Software");
527 | app.init(argc, argv);
528 | g_main_window = new MainWindow(&app);
529 | app.create();
530 | app.run();
531 | return 0;
532 | }
533 |
--------------------------------------------------------------------------------
/hidapi/testgui/testgui.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 10.00
3 | # Visual C++ Express 2008
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testgui", "testgui.vcproj", "{08769AC3-785A-4DDC-BFC7-1775414B7AB7}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Win32 = Debug|Win32
9 | Release|Win32 = Release|Win32
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {08769AC3-785A-4DDC-BFC7-1775414B7AB7}.Debug|Win32.ActiveCfg = Debug|Win32
13 | {08769AC3-785A-4DDC-BFC7-1775414B7AB7}.Debug|Win32.Build.0 = Debug|Win32
14 | {08769AC3-785A-4DDC-BFC7-1775414B7AB7}.Release|Win32.ActiveCfg = Release|Win32
15 | {08769AC3-785A-4DDC-BFC7-1775414B7AB7}.Release|Win32.Build.0 = Release|Win32
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/hidapi/testgui/testgui.vcproj:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
26 |
29 |
32 |
35 |
38 |
41 |
53 |
56 |
59 |
62 |
73 |
76 |
79 |
82 |
85 |
88 |
91 |
95 |
96 |
104 |
107 |
110 |
113 |
116 |
119 |
131 |
134 |
137 |
140 |
153 |
156 |
159 |
162 |
165 |
168 |
171 |
175 |
176 |
177 |
178 |
179 |
180 |
185 |
188 |
189 |
192 |
193 |
194 |
199 |
202 |
203 |
204 |
209 |
210 |
213 |
214 |
215 |
216 |
217 |
218 |
--------------------------------------------------------------------------------
/hidapi/udev/99-hid.rules:
--------------------------------------------------------------------------------
1 | # This is a sample udev file for HIDAPI devices which changes the permissions
2 | # to 0666 (world readable/writable) for a specified device on Linux systems.
3 |
4 |
5 | # If you are using the libusb implementation of hidapi (libusb/hid.c), then
6 | # use something like the following line, substituting the VID and PID with
7 | # those of your device. Note that for kernels before 2.6.24, you will need
8 | # to substitute "usb" with "usb_device". It shouldn't hurt to use two lines
9 | # (one each way) for compatibility with older systems.
10 |
11 | # HIDAPI/libusb
12 | SUBSYSTEM=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="003f", MODE="0666"
13 |
14 |
15 | # If you are using the hidraw implementation (linux/hid.c), then do something
16 | # like the following, substituting the VID and PID with your device. Busnum 1
17 | # is USB.
18 |
19 | # HIDAPI/hidraw
20 | KERNEL=="hidraw*", ATTRS{busnum}=="1", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="003f", MODE="0666"
21 |
22 | # Once done, optionally rename this file for your device, and drop it into
23 | # /etc/udev/rules.d and unplug and re-plug your device. This is all that is
24 | # necessary to see the new permissions. Udev does not have to be restarted.
25 |
26 | # Note that the hexadecimal values for VID and PID are case sensitive and
27 | # must be lower case.
28 |
29 | # If you think permissions of 0666 are too loose, then see:
30 | # http://reactivated.net/writing_udev_rules.html for more information on finer
31 | # grained permission setting. For example, it might be sufficient to just
32 | # set the group or user owner for specific devices (for example the plugdev
33 | # group on some systems).
34 |
--------------------------------------------------------------------------------
/hidapi/windows/.gitignore:
--------------------------------------------------------------------------------
1 | Debug
2 | Release
3 | .vs/
4 | *.exp
5 | *.ilk
6 | *.lib
7 | *.suo
8 | *.vcproj.*
9 | *.vcxproj.*
10 | *.ncb
11 | *.suo
12 | *.dll
13 | *.pdb
14 | .deps
15 | .libs
16 | *.lo
17 | *.la
18 |
--------------------------------------------------------------------------------
/hidapi/windows/Makefile-manual:
--------------------------------------------------------------------------------
1 |
2 |
3 | OS=$(shell uname)
4 |
5 | ifneq (,$(findstring MINGW,$(OS)))
6 | FILE=Makefile.mingw
7 | endif
8 |
9 | ifeq ($(FILE), )
10 | all:
11 | $(error Your platform ${OS} is not supported at this time.)
12 | endif
13 |
14 | include $(FILE)
15 |
--------------------------------------------------------------------------------
/hidapi/windows/Makefile.am:
--------------------------------------------------------------------------------
1 | lib_LTLIBRARIES = libhidapi.la
2 | libhidapi_la_SOURCES = hid.c
3 | libhidapi_la_LDFLAGS = $(LTLDFLAGS)
4 | AM_CPPFLAGS = -I$(top_srcdir)/hidapi/
5 | libhidapi_la_LIBADD = $(LIBS)
6 |
7 | hdrdir = $(includedir)/hidapi
8 | hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h
9 |
10 | EXTRA_DIST = \
11 | ddk_build \
12 | hidapi.vcproj \
13 | hidtest.vcproj \
14 | Makefile-manual \
15 | Makefile.mingw \
16 | hidapi.sln
17 |
--------------------------------------------------------------------------------
/hidapi/windows/Makefile.mingw:
--------------------------------------------------------------------------------
1 | ###########################################
2 | # Simple Makefile for HIDAPI test program
3 | #
4 | # Alan Ott
5 | # Signal 11 Software
6 | # 2010-06-01
7 | ###########################################
8 |
9 | all: hidtest libhidapi.dll
10 |
11 | CC=gcc
12 | CXX=g++
13 | COBJS=hid.o
14 | CPPOBJS=../hidtest/hidtest.o
15 | OBJS=$(COBJS) $(CPPOBJS)
16 | CFLAGS=-I../hidapi -g -c
17 | LIBS= -lsetupapi
18 | DLL_LDFLAGS = -mwindows -lsetupapi
19 |
20 | hidtest: $(OBJS)
21 | g++ -g $^ $(LIBS) -o hidtest
22 |
23 | libhidapi.dll: $(OBJS)
24 | $(CC) -g $^ $(DLL_LDFLAGS) -o libhidapi.dll
25 |
26 | $(COBJS): %.o: %.c
27 | $(CC) $(CFLAGS) $< -o $@
28 |
29 | $(CPPOBJS): %.o: %.cpp
30 | $(CXX) $(CFLAGS) $< -o $@
31 |
32 | clean:
33 | rm *.o ../hidtest/*.o hidtest.exe
34 |
35 | .PHONY: clean
36 |
--------------------------------------------------------------------------------
/hidapi/windows/ddk_build/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | obj*_*_*
--------------------------------------------------------------------------------
/hidapi/windows/ddk_build/hidapi.def:
--------------------------------------------------------------------------------
1 | LIBRARY hidapi
2 | EXPORTS
3 | hid_open @1
4 | hid_write @2
5 | hid_read @3
6 | hid_close @4
7 | hid_get_product_string @5
8 | hid_get_manufacturer_string @6
9 | hid_get_serial_number_string @7
10 | hid_get_indexed_string @8
11 | hid_error @9
12 | hid_set_nonblocking @10
13 | hid_enumerate @11
14 | hid_open_path @12
15 | hid_send_feature_report @13
16 | hid_get_feature_report @14
17 | hid_get_input_report @15
18 |
--------------------------------------------------------------------------------
/hidapi/windows/ddk_build/sources:
--------------------------------------------------------------------------------
1 | TARGETNAME=hidapi
2 | TARGETTYPE=DYNLINK
3 | UMTYPE=console
4 | UMENTRY=main
5 |
6 | MSC_WARNING_LEVEL=/W3 /WX
7 |
8 | TARGETLIBS=$(SDK_LIB_PATH)\hid.lib \
9 | $(SDK_LIB_PATH)\setupapi.lib \
10 | $(SDK_LIB_PATH)\kernel32.lib \
11 | $(SDK_LIB_PATH)\comdlg32.lib
12 |
13 | USE_MSVCRT=1
14 |
15 | INCLUDES= ..\..\hidapi
16 | SOURCES= ..\hid.c \
17 |
18 |
19 | TARGET_DESTINATION=retail
20 |
21 | MUI=0
22 | MUI_COMMENT="HID Interface DLL"
23 |
24 |
--------------------------------------------------------------------------------
/hidapi/windows/hidapi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.136
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hidapi", "hidapi.vcxproj", "{A107C21C-418A-4697-BB10-20C3AA60E2E4}"
7 | EndProject
8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hidtest", "hidtest.vcxproj", "{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Win32 = Debug|Win32
13 | Debug|x64 = Debug|x64
14 | Release|Win32 = Release|Win32
15 | Release|x64 = Release|x64
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|Win32.ActiveCfg = Debug|Win32
19 | {A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|Win32.Build.0 = Debug|Win32
20 | {A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|x64.ActiveCfg = Debug|x64
21 | {A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|x64.Build.0 = Debug|x64
22 | {A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|Win32.ActiveCfg = Release|Win32
23 | {A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|Win32.Build.0 = Release|Win32
24 | {A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|x64.ActiveCfg = Release|x64
25 | {A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|x64.Build.0 = Release|x64
26 | {23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Debug|Win32.ActiveCfg = Debug|Win32
27 | {23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Debug|Win32.Build.0 = Debug|Win32
28 | {23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Debug|x64.ActiveCfg = Debug|x64
29 | {23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Debug|x64.Build.0 = Debug|x64
30 | {23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Release|Win32.ActiveCfg = Release|Win32
31 | {23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Release|Win32.Build.0 = Release|Win32
32 | {23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Release|x64.ActiveCfg = Release|x64
33 | {23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Release|x64.Build.0 = Release|x64
34 | EndGlobalSection
35 | GlobalSection(SolutionProperties) = preSolution
36 | HideSolutionNode = FALSE
37 | EndGlobalSection
38 | GlobalSection(ExtensibilityGlobals) = postSolution
39 | SolutionGuid = {8749E535-9C65-4A89-840E-78D7578C7866}
40 | EndGlobalSection
41 | EndGlobal
42 |
--------------------------------------------------------------------------------
/hidapi/windows/hidapi.vcproj:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
26 |
29 |
32 |
35 |
38 |
41 |
53 |
56 |
59 |
62 |
70 |
73 |
76 |
79 |
82 |
85 |
88 |
91 |
92 |
100 |
103 |
106 |
109 |
112 |
115 |
127 |
130 |
133 |
136 |
146 |
149 |
152 |
155 |
158 |
161 |
164 |
167 |
168 |
169 |
170 |
171 |
172 |
177 |
180 |
181 |
182 |
187 |
190 |
191 |
192 |
197 |
198 |
199 |
200 |
201 |
202 |
--------------------------------------------------------------------------------
/hidapi/windows/hidapi.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Debug
10 | x64
11 |
12 |
13 | Release
14 | Win32
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | {A107C21C-418A-4697-BB10-20C3AA60E2E4}
23 | hidapi
24 | Win32Proj
25 |
26 |
27 |
28 | DynamicLibrary
29 | v140
30 | Unicode
31 | true
32 |
33 |
34 | DynamicLibrary
35 | v140
36 | Unicode
37 | true
38 |
39 |
40 | DynamicLibrary
41 | v140
42 | Unicode
43 |
44 |
45 | DynamicLibrary
46 | v140
47 | Unicode
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | <_ProjectFileVersion>14.0.25431.1
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | Disabled
75 | ..\hidapi;%(AdditionalIncludeDirectories)
76 | WIN32;_DEBUG;_WINDOWS;_USRDLL;HIDAPI_EXPORTS;%(PreprocessorDefinitions)
77 | true
78 | EnableFastChecks
79 | MultiThreadedDebugDLL
80 |
81 | Level3
82 | EditAndContinue
83 |
84 |
85 | setupapi.lib;%(AdditionalDependencies)
86 | true
87 | Windows
88 | MachineX86
89 |
90 |
91 |
92 |
93 | Disabled
94 | ..\hidapi;%(AdditionalIncludeDirectories)
95 | WIN32;_DEBUG;_WINDOWS;_USRDLL;HIDAPI_EXPORTS;%(PreprocessorDefinitions)
96 | EnableFastChecks
97 | MultiThreadedDebugDLL
98 |
99 |
100 | Level3
101 | EditAndContinue
102 |
103 |
104 | setupapi.lib;%(AdditionalDependencies)
105 | true
106 | Windows
107 |
108 |
109 |
110 |
111 | MaxSpeed
112 | true
113 | ..\hidapi;%(AdditionalIncludeDirectories)
114 | WIN32;NDEBUG;_WINDOWS;_USRDLL;HIDAPI_EXPORTS;%(PreprocessorDefinitions)
115 | MultiThreaded
116 | true
117 |
118 | Level3
119 | ProgramDatabase
120 |
121 |
122 | setupapi.lib;%(AdditionalDependencies)
123 | true
124 | Windows
125 | true
126 | true
127 | MachineX86
128 |
129 |
130 |
131 |
132 | MaxSpeed
133 | true
134 | ..\hidapi;%(AdditionalIncludeDirectories)
135 | WIN32;NDEBUG;_WINDOWS;_USRDLL;HIDAPI_EXPORTS;%(PreprocessorDefinitions)
136 | MultiThreaded
137 | true
138 |
139 |
140 | Level3
141 | ProgramDatabase
142 |
143 |
144 | setupapi.lib;%(AdditionalDependencies)
145 | true
146 | Windows
147 | true
148 | true
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/hidapi/windows/hidtest.vcproj:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
25 |
28 |
31 |
34 |
37 |
40 |
50 |
53 |
56 |
59 |
67 |
70 |
73 |
76 |
79 |
82 |
85 |
90 |
91 |
99 |
102 |
105 |
108 |
111 |
114 |
124 |
127 |
130 |
133 |
143 |
146 |
149 |
152 |
155 |
158 |
161 |
166 |
167 |
168 |
169 |
170 |
171 |
176 |
179 |
180 |
181 |
186 |
187 |
192 |
193 |
194 |
195 |
196 |
197 |
--------------------------------------------------------------------------------
/hidapi/windows/hidtest.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Debug
10 | x64
11 |
12 |
13 | Release
14 | Win32
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | {23E9FF6A-49D1-4993-B2B5-BBB992C6C712}
23 | hidtest
24 |
25 |
26 |
27 | Application
28 | v140
29 | MultiByte
30 | true
31 |
32 |
33 | Application
34 | v140
35 | MultiByte
36 | true
37 |
38 |
39 | Application
40 | v140
41 | MultiByte
42 |
43 |
44 | Application
45 | v140
46 | MultiByte
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | <_ProjectFileVersion>14.0.25431.1
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | Disabled
74 | ..\hidapi;%(AdditionalIncludeDirectories)
75 | true
76 | EnableFastChecks
77 | MultiThreadedDebugDLL
78 | Level3
79 | EditAndContinue
80 |
81 |
82 | hidapi.lib;%(AdditionalDependencies)
83 | $(SolutionDir)$(Configuration);%(AdditionalLibraryDirectories)
84 | true
85 | Console
86 | MachineX86
87 |
88 |
89 |
90 |
91 | Disabled
92 | ..\hidapi;%(AdditionalIncludeDirectories)
93 | EnableFastChecks
94 | MultiThreadedDebugDLL
95 | Level3
96 | EditAndContinue
97 |
98 |
99 | hidapi.lib;%(AdditionalDependencies)
100 | $(SolutionDir)$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)
101 | true
102 | Console
103 |
104 |
105 |
106 |
107 | MaxSpeed
108 | true
109 | ..\hidapi;%(AdditionalIncludeDirectories)
110 | MultiThreaded
111 | true
112 | Level3
113 | ProgramDatabase
114 |
115 |
116 | hidapi.lib;%(AdditionalDependencies)
117 | $(SolutionDir)$(Configuration);%(AdditionalLibraryDirectories)
118 | true
119 | Console
120 | true
121 | true
122 | MachineX86
123 |
124 |
125 |
126 |
127 | MaxSpeed
128 | true
129 | ..\hidapi;%(AdditionalIncludeDirectories)
130 | MultiThreaded
131 | true
132 | Level3
133 | ProgramDatabase
134 |
135 |
136 | hidapi.lib;%(AdditionalDependencies)
137 | $(SolutionDir)$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)
138 | true
139 | Console
140 | true
141 | true
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 | {a107c21c-418a-4697-bb10-20c3aa60e2e4}
150 | false
151 |
152 |
153 |
154 |
155 |
156 |
157 |
--------------------------------------------------------------------------------
/img/Logo.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erikmwerner/QJoyControl/0c6495329d13d62b42ef26271646a1393028e4e2/img/Logo.icns
--------------------------------------------------------------------------------
/img/Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erikmwerner/QJoyControl/0c6495329d13d62b42ef26271646a1393028e4e2/img/Logo.png
--------------------------------------------------------------------------------
/img/Logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
82 |
--------------------------------------------------------------------------------
/img/batt_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erikmwerner/QJoyControl/0c6495329d13d62b42ef26271646a1393028e4e2/img/batt_0.png
--------------------------------------------------------------------------------
/img/batt_0_chr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erikmwerner/QJoyControl/0c6495329d13d62b42ef26271646a1393028e4e2/img/batt_0_chr.png
--------------------------------------------------------------------------------
/img/batt_100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erikmwerner/QJoyControl/0c6495329d13d62b42ef26271646a1393028e4e2/img/batt_100.png
--------------------------------------------------------------------------------
/img/batt_100_chr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erikmwerner/QJoyControl/0c6495329d13d62b42ef26271646a1393028e4e2/img/batt_100_chr.png
--------------------------------------------------------------------------------
/img/batt_25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erikmwerner/QJoyControl/0c6495329d13d62b42ef26271646a1393028e4e2/img/batt_25.png
--------------------------------------------------------------------------------
/img/batt_25_chr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erikmwerner/QJoyControl/0c6495329d13d62b42ef26271646a1393028e4e2/img/batt_25_chr.png
--------------------------------------------------------------------------------
/img/batt_50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erikmwerner/QJoyControl/0c6495329d13d62b42ef26271646a1393028e4e2/img/batt_50.png
--------------------------------------------------------------------------------
/img/batt_50_chr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erikmwerner/QJoyControl/0c6495329d13d62b42ef26271646a1393028e4e2/img/batt_50_chr.png
--------------------------------------------------------------------------------
/img/batt_75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erikmwerner/QJoyControl/0c6495329d13d62b42ef26271646a1393028e4e2/img/batt_75.png
--------------------------------------------------------------------------------
/img/batt_75_chr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erikmwerner/QJoyControl/0c6495329d13d62b42ef26271646a1393028e4e2/img/batt_75_chr.png
--------------------------------------------------------------------------------
/img/retail_colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/inputmappanel.cpp:
--------------------------------------------------------------------------------
1 | #include "inputmappanel.h"
2 | #include "ui_inputmappanel.h"
3 |
4 | InputMapPanel::InputMapPanel(QWidget *parent) :
5 | QWidget(parent),
6 | ui(new Ui::InputMapPanel)
7 | {
8 | ui->setupUi(this);
9 | }
10 |
11 | InputMapPanel::~InputMapPanel()
12 | {
13 | delete ui;
14 | }
15 |
16 | InputMapWidget* InputMapPanel::addMapper(InputMapWidget* mapper)
17 | {
18 | // row, col, row span, col span
19 | ui->gridLayout->addWidget(mapper, ui->gridLayout->rowCount(), 0, 1, 3);
20 | return mapper;
21 | }
22 |
23 | void InputMapPanel::setName(QString name)
24 | {
25 | ui->groupBox->setTitle(name);
26 | }
27 |
--------------------------------------------------------------------------------
/inputmappanel.h:
--------------------------------------------------------------------------------
1 | #ifndef INPUTMAPPANEL_H
2 | #define INPUTMAPPANEL_H
3 |
4 | #include
5 | #include "inputmapwidget.h"
6 |
7 | class InputMapWidget;
8 |
9 | namespace Ui {
10 | class InputMapPanel;
11 | }
12 |
13 | class InputMapPanel : public QWidget
14 | {
15 | Q_OBJECT
16 |
17 | public:
18 | explicit InputMapPanel(QWidget *parent = nullptr);
19 | ~InputMapPanel();
20 | InputMapWidget *addMapper(InputMapWidget* mapper);
21 | void setName(QString name);
22 |
23 | private:
24 | Ui::InputMapPanel *ui;
25 | };
26 |
27 | #endif // INPUTMAPPANEL_H
28 |
--------------------------------------------------------------------------------
/inputmappanel.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | InputMapPanel
4 |
5 |
6 |
7 | 0
8 | 0
9 | 116
10 | 57
11 |
12 |
13 |
14 |
15 | 10
16 |
17 |
18 |
19 | Form
20 |
21 |
22 | -
23 |
24 |
25 |
26 | 10
27 |
28 |
29 |
30 | groupbox
31 |
32 |
33 |
34 | 0
35 |
36 |
37 | 0
38 |
39 |
40 | 2
41 |
42 |
-
43 |
44 |
45 |
46 | 10
47 |
48 |
49 |
50 | Button
51 |
52 |
53 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
54 |
55 |
56 |
57 | -
58 |
59 |
60 |
61 | 10
62 |
63 |
64 |
65 | Key
66 |
67 |
68 |
69 | -
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/inputmapwidget.cpp:
--------------------------------------------------------------------------------
1 | #include "inputmapwidget.h"
2 | #include "ui_inputmapwidget.h"
3 | #include
4 | #include
5 | #include "mainwindow.h"
6 | #include "eventhandler.h"
7 |
8 | #include
9 | #include
10 |
11 | InputMapWidget::InputMapWidget(QString button_name, int button_mask, int key_code, EventHandler* handler, QWidget *parent) :
12 | QWidget(parent),
13 | ui(new Ui::InputMapWidget),
14 | _handler(handler),
15 | _grab_timer(new QTimer(this)),
16 | _button_mask(button_mask),
17 | _button_name(button_name),
18 | _key_code(key_code),
19 | _wait_key(false)
20 | {
21 | ui->setupUi(this);
22 | QSettings settings;
23 | if(settings.contains("key-map/" + QString::number(_button_mask)) ) {
24 | int code = settings.value("key-map/" + QString::number(_button_mask)).toInt();
25 | _key_code = code;
26 | }
27 |
28 | connect(_grab_timer,SIGNAL(timeout()),this,SLOT(onGrabTimerTimeout()));
29 | ui->labelButton->setText(button_name);
30 | displayKeyCodeString();
31 | handler->addMapping(_button_mask, _key_code);
32 | }
33 |
34 | InputMapWidget::~InputMapWidget()
35 | {
36 | QSettings settings;//("werner", "QJoyControl");
37 | settings.beginGroup("key-map");
38 | settings.setValue(QString::number(_button_mask), _key_code);
39 | settings.endGroup();
40 |
41 | delete ui;
42 | }
43 |
44 | void InputMapWidget::displayKeyCodeString()
45 | {
46 | Qt::Key key = (Qt::Key)_key_code;
47 | ui->labelKeyCode->setText(QKeySequence(key).toString());
48 | }
49 |
50 | void InputMapWidget::on_toolButtonSet_clicked()
51 | {
52 | // get the next keypress
53 | _wait_key = true;
54 | grab_timer_count = 0;
55 | ui->toolButtonSet->setText(QString::number(10 - grab_timer_count) + "...");
56 | ui->toolButtonSet->setEnabled(false);
57 | grabKeyboard();
58 | _grab_timer->start(1000);
59 | }
60 |
61 | void InputMapWidget::keyPressEvent(QKeyEvent *event)
62 | {
63 | if(_wait_key){
64 | _key_code = event->key();
65 | _handler->addMapping(_button_mask, _key_code);
66 | displayKeyCodeString();
67 | _grab_timer->stop();
68 | onGrabKeyFinished();
69 | }
70 | else {
71 | QWidget::keyPressEvent(event);
72 | }
73 | }
74 |
75 | void InputMapWidget::onGrabTimerTimeout()
76 | {
77 | grab_timer_count++;
78 | ui->toolButtonSet->setText(QString::number(10 - grab_timer_count) + "...");
79 | if(grab_timer_count > 10)
80 | {
81 | onGrabKeyFinished();
82 | }
83 | }
84 |
85 | void InputMapWidget::onGrabKeyFinished()
86 | {
87 | _wait_key = false;
88 | // release the keyboard
89 | releaseKeyboard();
90 | _grab_timer->stop();
91 | ui->toolButtonSet->setText("Set");
92 | ui->toolButtonSet->setEnabled(true);
93 | }
94 |
95 | void InputMapWidget::setClickMap(int code)
96 | {
97 | if(code == 0) { // no click
98 | setEnabled(true);
99 | _handler->addMapping(_button_mask, _key_code);
100 | }
101 | else if(code == 1) { // right click
102 | setEnabled(false);
103 | _handler->mapToMouseButton(_button_mask, 1);
104 | //_handler->addMapping(_button_mask, kCGEventRightMouseDown);
105 | }
106 | else if (code == 2) { // left click
107 | setEnabled(false);
108 | _handler->mapToMouseButton(_button_mask, 2);
109 | // _handler->addMapping(_button_mask, kCGEventLeftMouseDown);
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/inputmapwidget.h:
--------------------------------------------------------------------------------
1 | #ifndef INPUTMAPWIDGET_H
2 | #define INPUTMAPWIDGET_H
3 |
4 | #include
5 |
6 | class EventHandler;
7 |
8 | namespace Ui {
9 | class InputMapWidget;
10 | }
11 |
12 | class InputMapWidget : public QWidget
13 | {
14 | Q_OBJECT
15 |
16 | public:
17 | explicit InputMapWidget(QString button_name, int button_mask, int key_code, EventHandler* handler, QWidget *parent = nullptr);
18 | ~InputMapWidget();
19 |
20 | void setClickMap(int code);
21 | protected:
22 | void keyPressEvent(QKeyEvent *event);
23 |
24 | private slots:
25 | void on_toolButtonSet_clicked();
26 | void onGrabTimerTimeout();
27 | void onGrabKeyFinished();
28 |
29 | private:
30 | void displayKeyCodeString();
31 |
32 | Ui::InputMapWidget *ui;
33 | EventHandler* _handler = nullptr;
34 | QTimer* _grab_timer = nullptr;
35 | int grab_timer_count = 0;
36 | int _button_mask = 0;
37 | QString _button_name;
38 | int _key_code;
39 | bool _wait_key;;
40 | };
41 |
42 | #endif // INPUTMAPWIDGET_H
43 |
--------------------------------------------------------------------------------
/inputmapwidget.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | InputMapWidget
4 |
5 |
6 |
7 | 0
8 | 0
9 | 103
10 | 19
11 |
12 |
13 |
14 |
15 | 10
16 |
17 |
18 |
19 | Form
20 |
21 |
22 |
23 |
24 |
25 |
26 | 0
27 |
28 |
29 | 0
30 |
31 |
32 | 0
33 |
34 |
35 | 0
36 |
37 |
38 | 6
39 |
40 |
41 | 0
42 |
43 | -
44 |
45 |
46 | Set
47 |
48 |
49 |
50 | -
51 |
52 |
53 |
54 | 10
55 |
56 |
57 |
58 | Value
59 |
60 |
61 |
62 | -
63 |
64 |
65 |
66 | 10
67 |
68 |
69 |
70 | Button
71 |
72 |
73 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/ir_sensor.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // crc-8-ccitt / polynomial 0x07 look up table
4 | static uint8_t mcu_crc8_table[256] = {
5 | 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
6 | 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
7 | 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
8 | 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
9 | 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
10 | 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
11 | 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
12 | 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
13 | 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
14 | 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
15 | 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
16 | 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
17 | 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
18 | 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
19 | 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
20 | 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
21 | };
22 |
23 | // ARGB Ironbow palette
24 | static uint32_t iron_palette[] = {
25 | 0xff000014, 0xff000025, 0xff00002a, 0xff000032, 0xff000036, 0xff00003e, 0xff000042, 0xff00004f,
26 | 0xff010055, 0xff010057, 0xff02005c, 0xff03005e, 0xff040063, 0xff050065, 0xff070069, 0xff0a0070,
27 | 0xff0b0073, 0xff0d0075, 0xff0d0076, 0xff100078, 0xff120079, 0xff15007c, 0xff17007d, 0xff1c0081,
28 | 0xff200084, 0xff220085, 0xff260087, 0xff280089, 0xff2c008a, 0xff2e008b, 0xff32008d, 0xff38008f,
29 | 0xff390090, 0xff3c0092, 0xff3e0093, 0xff410094, 0xff420095, 0xff450096, 0xff470096, 0xff4c0097,
30 | 0xff4f0097, 0xff510097, 0xff540098, 0xff560098, 0xff5a0099, 0xff5c0099, 0xff5f009a, 0xff64009b,
31 | 0xff66009b, 0xff6a009b, 0xff6c009c, 0xff6f009c, 0xff70009c, 0xff73009d, 0xff75009d, 0xff7a009d,
32 | 0xff7e009d, 0xff7f009d, 0xff83009d, 0xff84009d, 0xff87009d, 0xff89009d, 0xff8b009d, 0xff91009c,
33 | 0xff93009c, 0xff96009b, 0xff98009b, 0xff9b009b, 0xff9c009b, 0xff9f009b, 0xffa0009b, 0xffa4009b,
34 | 0xffa7009a, 0xffa8009a, 0xffaa0099, 0xffab0099, 0xffae0198, 0xffaf0198, 0xffb00198, 0xffb30196,
35 | 0xffb40296, 0xffb60295, 0xffb70395, 0xffb90495, 0xffba0495, 0xffbb0593, 0xffbc0593, 0xffbf0692,
36 | 0xffc00791, 0xffc00791, 0xffc10990, 0xffc20a8f, 0xffc30b8e, 0xffc40c8d, 0xffc60d8b, 0xffc81088,
37 | 0xffc91187, 0xffca1385, 0xffcb1385, 0xffcc1582, 0xffcd1681, 0xffce187e, 0xffcf187c, 0xffd11b78,
38 | 0xffd21c75, 0xffd21d74, 0xffd32071, 0xffd4216f, 0xffd5236b, 0xffd52469, 0xffd72665, 0xffd92a60,
39 | 0xffda2b5e, 0xffdb2e5a, 0xffdb2f57, 0xffdd3051, 0xffdd314e, 0xffde3347, 0xffdf3444, 0xffe0373a,
40 | 0xffe03933, 0xffe13a30, 0xffe23c2a, 0xffe33d26, 0xffe43f20, 0xffe4411d, 0xffe5431b, 0xffe64616,
41 | 0xffe74715, 0xffe74913, 0xffe84a12, 0xffe84c0f, 0xffe94d0e, 0xffea4e0c, 0xffea4f0c, 0xffeb520a,
42 | 0xffec5409, 0xffec5608, 0xffec5808, 0xffed5907, 0xffed5b06, 0xffee5c06, 0xffee5d05, 0xffef6004,
43 | 0xffef6104, 0xfff06303, 0xfff06403, 0xfff16603, 0xfff16603, 0xfff16803, 0xfff16902, 0xfff16b02,
44 | 0xfff26d01, 0xfff26e01, 0xfff37001, 0xfff37101, 0xfff47300, 0xfff47400, 0xfff47600, 0xfff47a00,
45 | 0xfff57b00, 0xfff57e00, 0xfff57f00, 0xfff68100, 0xfff68200, 0xfff78400, 0xfff78500, 0xfff88800,
46 | 0xfff88900, 0xfff88a00, 0xfff88c00, 0xfff98d00, 0xfff98e00, 0xfff98f00, 0xfff99100, 0xfffa9400,
47 | 0xfffa9500, 0xfffb9800, 0xfffb9900, 0xfffb9c00, 0xfffc9d00, 0xfffca000, 0xfffca100, 0xfffda400,
48 | 0xfffda700, 0xfffda800, 0xfffdab00, 0xfffdac00, 0xfffdae00, 0xfffeaf00, 0xfffeb100, 0xfffeb400,
49 | 0xfffeb500, 0xfffeb800, 0xfffeb900, 0xfffeba00, 0xfffebb00, 0xfffebd00, 0xfffebe00, 0xfffec200,
50 | 0xfffec400, 0xfffec500, 0xfffec700, 0xfffec800, 0xfffeca01, 0xfffeca01, 0xfffecc02, 0xfffecf04,
51 | 0xfffecf04, 0xfffed106, 0xfffed308, 0xfffed50a, 0xfffed60a, 0xfffed80c, 0xfffed90d, 0xffffdb10,
52 | 0xffffdc14, 0xffffdd16, 0xffffde1b, 0xffffdf1e, 0xffffe122, 0xffffe224, 0xffffe328, 0xffffe531,
53 | 0xffffe635, 0xffffe73c, 0xffffe83f, 0xffffea46, 0xffffeb49, 0xffffec50, 0xffffed54, 0xffffee5f,
54 | 0xffffef67, 0xfffff06a, 0xfffff172, 0xfffff177, 0xfffff280, 0xfffff285, 0xfffff38e, 0xfffff49a,
55 | 0xfffff59e, 0xfffff5a6, 0xfffff6aa, 0xfffff7b3, 0xfffff7b6, 0xfffff8bd, 0xfffff8c1, 0xfffff9ca,
56 | 0xfffffad1, 0xfffffad4, 0xfffffcdb, 0xfffffcdf, 0xfffffde5, 0xfffffde8, 0xfffffeee, 0xfffffff6
57 | };
58 |
59 |
--------------------------------------------------------------------------------
/joyconworker.h:
--------------------------------------------------------------------------------
1 | #ifndef JOYCONTHREAD_H
2 | #define JOYCONTHREAD_H
3 |
4 | #include
5 | #include
6 | //#include
7 | #include "hidapi.h"
8 | #include
9 |
10 | //struct hid_device;
11 | //#include
12 |
13 | class EventHandler;
14 |
15 | Q_DECLARE_METATYPE(QList)
16 | Q_DECLARE_METATYPE(QList)
17 | Q_DECLARE_METATYPE(QList)
18 |
19 | const unsigned short NINTENDO = 1406; // 0x057e
20 | const unsigned short JOYCON_L = 8198; // 0x2006
21 | const unsigned short JOYCON_R = 8199; // 0x2007
22 | const unsigned short PRO_CONTROLLER = 8201; // 0x2009
23 |
24 |
25 | // Limit a value to the range [low, high]
26 | template T CLAMP(const T& value, const T& low, const T& high)
27 | {
28 | return value < low ? low : (value > high ? high : value);
29 | }
30 |
31 | // From: https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/bluetooth_hid_notes.md
32 | enum JC_CMD {
33 | // outputs:
34 | RUMBLE_PLUS = 0x01, // Output. Send a rumble and subcommand
35 | MCU_FW_UPDATE = 0x03, // Output. Send a FW update packet to the STM32 (IR/NFC MCU)
36 | RUMBLE_ONLY = 0x10, // Output. Send rumble data only
37 | MCU_DATA = 0x11, // Output. Request data from the STM32. Can also send rumble
38 | //0x12 // Unknown. Does the same as 0x28
39 |
40 | // inputs
41 | PUSH_INPUT = 0x3F,
42 | STANDARD_INPUT = 0x21, // Standard input reports used for subcommand replies
43 | MCU_UPDATE = 0x23, // NFC/IR MCU FW update input report.
44 | FULL_INPUT = 0x30, // Standard full mode - input reports with IMU data instead of subcommand replies. Pushes current state @60Hz, or @120Hz if Pro Controller.
45 | LARGE_PACKET = 0x31, // NFC/IR MCU mode. Pushes large packets with standard input report + NFC/IR MCU data input report.
46 | //0x32, // Unknown. Sends standard input reports.
47 | //0x33, // Unknown. Sends standard input reports.
48 |
49 | // feature reports
50 | GET_LAST_SUB = 0x02, // Get last subcommand reply
51 | ENABLE_OTA_FW = 0x70, // Enable OTA FW upgrade
52 | SETUP_MEM_READ = 0x71, // Setup memory read
53 | MEM_READ = 0x72, // Memory read
54 | MEM_ERASE = 0x73, // Memory sector erase
55 | MEM_WRITE = 0x74, // Memory sector write
56 | REBOOT = 0x75 // Reboots and executes the firmware rom in the given address
57 | // 0xCC, // Unknown send feature report
58 | // 0xFE, // Unknown get feature report
59 | };
60 |
61 | enum JC_SUBCMD {
62 | GET_STATE = 0x00,
63 | BT_PAIR = 0x01,
64 | GET_INFO = 0x02,
65 | SET_INPUT_MODE = 0x03,
66 | TRIGGER_ELAPSED = 0x04,
67 | GET_PAGE_LIST_STATE = 0x05,
68 | SET_HCI_STATE = 0x06,
69 | RESET_PAIR = 0x07,
70 | LOW_POWER = 0x08,
71 | SPI_READ = 0x10,
72 | SPI_WRITE = 0x11,
73 | SPI_ERASE = 0x12,
74 | STM32_RESET = 0x20,
75 | STM32_CONFIG = 0x21,
76 | STM32_SET_STATE = 0x22,
77 | // 0x24,
78 | // 0x25,
79 | // 0x28,
80 | // 0x29
81 | SET_GPIO2_VALUE = 0x2A,
82 | GET_STM32_Data = 0x2B,
83 | SET_PLAYER_LED = 0x30,
84 | GET_PLAYER_LED = 0x31,
85 | SET_HOME_LED = 0x38,
86 | ENABLE_IMU = 0x40,
87 | CONFIG_IMU = 0x41,
88 | WRITE_IMU = 0x42,
89 | READ_IMU = 0x43,
90 | ENABLE_VIB = 0x48,
91 | GET_VREG = 0x50,
92 | SET_GPIO1_VALUE = 0x51,
93 | GET_GPIO_VALUE = 0x52
94 | };
95 |
96 | #pragma pack(push, 1) // set current alignment packing value to 1 (MSVC)
97 |
98 | // a structure to hold a
99 | struct brcm_hdr { // 10 bytes total
100 | uint8_t cmd; // 0
101 | uint8_t timer; // 1
102 | uint8_t rumble_l[4]; // 2-5
103 | uint8_t rumble_r[4]; // 6-9
104 | };
105 |
106 | struct brcm_cmd_01 { // 49 bytes long
107 | uint8_t subcmd;
108 | union {
109 | struct {
110 | uint32_t offset;
111 | uint8_t size;
112 | } spi_data;
113 |
114 | struct {
115 | uint8_t arg1;
116 | uint8_t arg2;
117 | } subcmd_arg;
118 |
119 | struct {
120 | uint8_t mcu_cmd;
121 | uint8_t mcu_subcmd;
122 | uint8_t mcu_mode;
123 | } subcmd_21_21;
124 |
125 | struct {
126 | uint8_t mcu_cmd;
127 | uint8_t mcu_subcmd;
128 | uint8_t no_of_reg;
129 | uint16_t reg1_addr;
130 | uint8_t reg1_val;
131 | uint16_t reg2_addr;
132 | uint8_t reg2_val;
133 | uint16_t reg3_addr;
134 | uint8_t reg3_val;
135 | uint16_t reg4_addr;
136 | uint8_t reg4_val;
137 | uint16_t reg5_addr;
138 | uint8_t reg5_val;
139 | uint16_t reg6_addr;
140 | uint8_t reg6_val;
141 | uint16_t reg7_addr;
142 | uint8_t reg7_val;
143 | uint16_t reg8_addr;
144 | uint8_t reg8_val;
145 | uint16_t reg9_addr;
146 | uint8_t reg9_val;
147 | } subcmd_21_23_04;
148 |
149 | struct {
150 | uint8_t mcu_cmd;
151 | uint8_t mcu_subcmd;
152 | uint8_t mcu_ir_mode;
153 | uint8_t no_of_frags;
154 | uint16_t mcu_major_v;
155 | uint16_t mcu_minor_v;
156 | } subcmd_21_23_01;
157 | };
158 | };
159 |
160 | struct ir_image_config {
161 | uint8_t ir_res_reg;
162 | uint16_t ir_exposure;
163 | uint8_t ir_leds; // Leds to enable, Strobe/Flashlight modes
164 | uint16_t ir_leds_intensity; // MSByte: Leds 1/2, LSB: Leds 3/4
165 | uint8_t ir_digital_gain;
166 | uint8_t ir_ex_light_filter;
167 | uint32_t ir_custom_register; // MSByte: Enable/Disable, Middle Byte: Edge smoothing, LSB: Color interpolation
168 | uint16_t ir_buffer_update_time;
169 | uint8_t ir_hand_analysis_mode;
170 | uint8_t ir_hand_analysis_threshold;
171 | uint32_t ir_denoise; // MSByte: Enable/Disable, Middle Byte: Edge smoothing, LSB: Color interpolation
172 | uint8_t ir_flip;
173 | int width;
174 | int height;
175 | uint8_t max_fragment_no;// = 0xff;
176 | };
177 | Q_DECLARE_METATYPE(ir_image_config)
178 |
179 | #pragma pack(pop) // remove the last pack pragma
180 |
181 | class JoyConWorker : public QObject
182 | {
183 | Q_OBJECT
184 | public:
185 | explicit JoyConWorker(QObject *parent = nullptr);
186 | ~JoyConWorker();
187 |
188 | signals:
189 |
190 | //< returns an empty QString and zero if nothing is connected
191 | void deviceConnectionChanged(QString, const unsigned short);
192 |
193 | void deviceStatusMessage(QString); //< send messages to display on the status bar
194 |
195 | void newDeviceInfo(QList, int);
196 | void newTemperatureData(float);
197 | void newBatteryData(int, int, int);
198 | void newCameraImage(QImage);
199 |
200 | //< digital input data, analog input data
201 | void newInputData(QList, QList);
202 |
203 | void finished();
204 |
205 | public slots:
206 | void setup();
207 | void onConnectHID(unsigned short vendor_id,
208 | unsigned short product_id,
209 | const wchar_t *serial_number);
210 | void onDisconnectHID();
211 |
212 | void requestDeviceInfo();
213 | void requestTemperature();
214 | void requestBattery();
215 | void requestJoyConInputs();
216 |
217 | void onInputStreamingEnabled(bool enabled);
218 |
219 | void onIrConfigUpdated(ir_image_config ir_new_config);
220 | int get_raw_ir_image(unsigned char show_status = 0); //tk show status?
221 |
222 | private slots:
223 | void onInputPollTimerTimeout();
224 | void onDeviceStatusTimerTimeout();
225 | void onIrCaptureTimerTimeout();
226 |
227 | private:
228 | QTimer* _input_poll_timer = nullptr; //
3 | struct lut_amp {
4 | float amp_float[101];
5 | uint8_t ha[101];
6 | uint16_t la[101];
7 | };
8 |
9 | static lut_amp lut_joy_amp{
10 | { 0.00000f, 0.007843f, 0.011823f, 0.014061f, 0.01672f, 0.019885f, 0.023648f, 0.028123f,
11 | 0.033442f, 0.039771f, 0.047296f, 0.056246f, 0.066886f, 0.079542f, 0.094592f, 0.112491f,
12 | 0.117471f, 0.122671f, 0.128102f, 0.133774f, 0.139697f, 0.145882f, 0.152341f, 0.159085f,
13 | 0.166129f, 0.173484f, 0.181166f, 0.189185f, 0.197561f, 0.206308f, 0.215442f, 0.224982f,
14 | 0.229908f, 0.234943f, 0.240087f, 0.245345f, 0.250715f, 0.256206f, 0.261816f, 0.267549f,
15 | 0.273407f, 0.279394f, 0.285514f, 0.291765f, 0.298154f, 0.304681f, 0.311353f, 0.318171f,
16 | 0.325138f, 0.332258f, 0.339534f, 0.346969f, 0.354566f, 0.362331f, 0.370265f, 0.378372f,
17 | 0.386657f, 0.395124f, 0.403777f, 0.412619f, 0.421652f, 0.430885f, 0.440321f, 0.449964f,
18 | 0.459817f, 0.469885f, 0.480174f, 0.490689f, 0.501433f, 0.512413f, 0.523633f, 0.535100f,
19 | 0.546816f, 0.558790f, 0.571027f, 0.583530f, 0.596307f, 0.609365f, 0.622708f, 0.636344f,
20 | 0.650279f, 0.664518f, 0.679069f, 0.693939f, 0.709133f, 0.724662f, 0.740529f, 0.756745f,
21 | 0.773316f, 0.790249f, 0.807554f, 0.825237f, 0.843307f, 0.861772f, 0.880643f, 0.899928f,
22 | 0.919633f, 0.939771f, 0.960348f, 0.981378f, 1.002867f },
23 |
24 | { 0x0, 0x2, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
25 | 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
26 | 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e,
27 | 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
28 | 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e,
29 | 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
30 | 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e,
31 | 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
32 | 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e,
33 | 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
34 | 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae,
35 | 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
36 | 0xc0, 0xc2, 0xc4, 0xc6, 0xc8 },
37 |
38 | { 0x0040, 0x8040, 0x0041, 0x8041, 0x0042, 0x8042, 0x0043, 0x8043,
39 | 0x0044, 0x8044, 0x0045, 0x8045, 0x0046, 0x8046, 0x0047, 0x8047,
40 | 0x0048, 0x8048, 0x0049, 0x8049, 0x004a, 0x804a, 0x004b, 0x804b,
41 | 0x004c, 0x804c, 0x004d, 0x804d, 0x004e, 0x804e, 0x004f, 0x804f,
42 | 0x0050, 0x8050, 0x0051, 0x8051, 0x0052, 0x8052, 0x0053, 0x8053,
43 | 0x0054, 0x8054, 0x0055, 0x8055, 0x0056, 0x8056, 0x0057, 0x8057,
44 | 0x0058, 0x8058, 0x0059, 0x8059, 0x005a, 0x805a, 0x005b, 0x805b,
45 | 0x005c, 0x805c, 0x005d, 0x805d, 0x005e, 0x805e, 0x005f, 0x805f,
46 | 0x0060, 0x8060, 0x0061, 0x8061, 0x0062, 0x8062, 0x0063, 0x8063,
47 | 0x0064, 0x8064, 0x0065, 0x8065, 0x0066, 0x8066, 0x0067, 0x8067,
48 | 0x0068, 0x8068, 0x0069, 0x8069, 0x006a, 0x806a, 0x006b, 0x806b,
49 | 0x006c, 0x806c, 0x006d, 0x806d, 0x006e, 0x806e, 0x006f, 0x806f,
50 | 0x0070, 0x8070, 0x0071, 0x8071, 0x0072 }
51 | };
52 |
53 |
--------------------------------------------------------------------------------
/mac/.gitignore:
--------------------------------------------------------------------------------
1 | Debug
2 | Release
3 | *.exp
4 | *.ilk
5 | *.lib
6 | *.suo
7 | *.vcproj.*
8 | *.ncb
9 | *.suo
10 | *.dll
11 | *.pdb
12 | *.o
13 | hidapi-hidtest
14 | .deps
15 | .libs
16 | *.la
17 | *.lo
18 |
--------------------------------------------------------------------------------
/mac/eventhandler_macos.cpp:
--------------------------------------------------------------------------------
1 | #include "eventhandler.h"
2 | #include
3 | #include
4 |
5 | // key code mappings
6 | // https://stackoverflow.com/questions/1918841/how-to-convert-ascii-character-to-cgkeycode/14529841#14529841][1]
7 |
8 | /* The CGKeyCodes enum is used by
9 | * MacOS Core Graphics to represent the virtual
10 | * key codes used in keyboard events
11 | */
12 |
13 | /*!
14 | * \brief EventHandler::EventHandler
15 | */
16 | EventHandler::EventHandler()
17 | {
18 | // CGKeyCodes from Events.h in carbon
19 | // based on US Extended keyboard
20 | qt_to_cg.insert(Qt::Key_A, kVK_ANSI_A);
21 | qt_to_cg.insert(Qt::Key_S, kVK_ANSI_S);
22 | qt_to_cg.insert(Qt::Key_D, kVK_ANSI_D);
23 | qt_to_cg.insert(Qt::Key_F, kVK_ANSI_F);
24 | qt_to_cg.insert(Qt::Key_H, kVK_ANSI_H);
25 | qt_to_cg.insert(Qt::Key_G, kVK_ANSI_G);
26 | qt_to_cg.insert(Qt::Key_Z, kVK_ANSI_Z);
27 | qt_to_cg.insert(Qt::Key_X, kVK_ANSI_X);
28 | qt_to_cg.insert(Qt::Key_C, kVK_ANSI_C);
29 | qt_to_cg.insert(Qt::Key_V, kVK_ANSI_V);
30 | qt_to_cg.insert(Qt::Key_B, kVK_ANSI_B);
31 | qt_to_cg.insert(Qt::Key_Q, kVK_ANSI_Q);
32 | qt_to_cg.insert(Qt::Key_W, kVK_ANSI_W);
33 | qt_to_cg.insert(Qt::Key_E, kVK_ANSI_E);
34 | qt_to_cg.insert(Qt::Key_R, kVK_ANSI_R);
35 | qt_to_cg.insert(Qt::Key_T, kVK_ANSI_T);
36 | qt_to_cg.insert(Qt::Key_Y, kVK_ANSI_Y);
37 |
38 | qt_to_cg.insert(Qt::Key_1, kVK_ANSI_1);
39 | qt_to_cg.insert(Qt::Key_2, kVK_ANSI_2);
40 | qt_to_cg.insert(Qt::Key_3, kVK_ANSI_3);
41 | qt_to_cg.insert(Qt::Key_4, kVK_ANSI_4);
42 | qt_to_cg.insert(Qt::Key_6, kVK_ANSI_6);
43 | qt_to_cg.insert(Qt::Key_5, kVK_ANSI_5);
44 | qt_to_cg.insert(Qt::Key_Equal, kVK_ANSI_Equal);
45 | qt_to_cg.insert(Qt::Key_9, kVK_ANSI_9);
46 | qt_to_cg.insert(Qt::Key_7, kVK_ANSI_7);
47 | qt_to_cg.insert(Qt::Key_Minus, kVK_ANSI_Minus);
48 | qt_to_cg.insert(Qt::Key_8, kVK_ANSI_8);
49 | qt_to_cg.insert(Qt::Key_0, kVK_ANSI_0);
50 | qt_to_cg.insert(Qt::Key_BracketRight, kVK_ANSI_RightBracket);
51 | qt_to_cg.insert(Qt::Key_O, kVK_ANSI_O);
52 | qt_to_cg.insert(Qt::Key_U, kVK_ANSI_U);
53 | qt_to_cg.insert(Qt::Key_BracketLeft, kVK_ANSI_LeftBracket);
54 | qt_to_cg.insert(Qt::Key_I, kVK_ANSI_I);
55 | qt_to_cg.insert(Qt::Key_P, kVK_ANSI_P);
56 | qt_to_cg.insert(Qt::Key_L, kVK_ANSI_L);
57 | qt_to_cg.insert(Qt::Key_J, kVK_ANSI_J);
58 | qt_to_cg.insert(Qt::Key_QuoteLeft, kVK_ANSI_Quote);
59 | qt_to_cg.insert(Qt::Key_K, kVK_ANSI_K);
60 | qt_to_cg.insert(Qt::Key_Semicolon, kVK_ANSI_Semicolon);
61 | qt_to_cg.insert(Qt::Key_Backslash, kVK_ANSI_Backslash);
62 | qt_to_cg.insert(Qt::Key_Comma, kVK_ANSI_Comma);
63 | qt_to_cg.insert(Qt::Key_Slash, kVK_ANSI_Slash);
64 | qt_to_cg.insert(Qt::Key_N, kVK_ANSI_N);
65 | qt_to_cg.insert(Qt::Key_M, kVK_ANSI_M);
66 | qt_to_cg.insert(Qt::Key_Period, kVK_ANSI_Period);
67 | qt_to_cg.insert(Qt::Key_Dead_Grave, kVK_ANSI_Grave);
68 | // there are more ansi...
69 |
70 | qt_to_cg.insert(Qt::Key_Return, kVK_Return);
71 | qt_to_cg.insert(Qt::Key_Tab, kVK_Tab);
72 | qt_to_cg.insert(Qt::Key_Space, kVK_Space);
73 | qt_to_cg.insert(Qt::Key_Delete, kVK_Delete);
74 | qt_to_cg.insert(Qt::Key_Escape, kVK_Escape);
75 | qt_to_cg.insert(Qt::Key_Control, kVK_Command);
76 | qt_to_cg.insert(Qt::Key_Period, kVK_Shift);
77 | qt_to_cg.insert(Qt::Key_CapsLock, kVK_CapsLock);
78 | qt_to_cg.insert(Qt::Key_Option, kVK_Option);
79 | qt_to_cg.insert(Qt::Key_Meta, kVK_Control);
80 | //qt_to_cg.insert(Qt::Key_Func kVK_Function);
81 | qt_to_cg.insert(Qt::Key_F17, kVK_F17);
82 | qt_to_cg.insert(Qt::Key_VolumeUp, kVK_VolumeUp);
83 | qt_to_cg.insert(Qt::Key_VolumeDown, kVK_VolumeDown);
84 | //qt_to_cg.insert(Qt::Key_Mute, kVK_Mute);
85 | qt_to_cg.insert(Qt::Key_F18, kVK_F18);
86 | qt_to_cg.insert(Qt::Key_F19, kVK_F19);
87 | qt_to_cg.insert(Qt::Key_F20, kVK_F20);
88 | qt_to_cg.insert(Qt::Key_F5, kVK_F5);
89 | qt_to_cg.insert(Qt::Key_F6, kVK_F6);
90 | qt_to_cg.insert(Qt::Key_F7, kVK_F7);
91 | qt_to_cg.insert(Qt::Key_F3, kVK_F3);
92 | qt_to_cg.insert(Qt::Key_F8, kVK_F8);
93 | qt_to_cg.insert(Qt::Key_F9, kVK_F9);
94 | qt_to_cg.insert(Qt::Key_F11, kVK_F11);
95 | qt_to_cg.insert(Qt::Key_F13, kVK_F13);
96 | qt_to_cg.insert(Qt::Key_F16, kVK_F16);
97 | qt_to_cg.insert(Qt::Key_F14, kVK_F14);
98 | qt_to_cg.insert(Qt::Key_F10, kVK_F10);
99 | qt_to_cg.insert(Qt::Key_F12, kVK_F12);
100 | qt_to_cg.insert(Qt::Key_F15, kVK_F15);
101 | qt_to_cg.insert(Qt::Key_Help, kVK_Help);
102 | qt_to_cg.insert(Qt::Key_Home, kVK_Home);
103 | qt_to_cg.insert(Qt::Key_PageUp, kVK_PageUp);
104 | qt_to_cg.insert(Qt::Key_Forward, kVK_ForwardDelete);
105 | qt_to_cg.insert(Qt::Key_F4, kVK_F4);
106 | qt_to_cg.insert(Qt::Key_End, kVK_End);
107 | qt_to_cg.insert(Qt::Key_F2, kVK_F2);
108 | qt_to_cg.insert(Qt::Key_PageDown, kVK_PageDown);
109 | qt_to_cg.insert(Qt::Key_F1, kVK_F1);
110 | qt_to_cg.insert(Qt::Key_Left, kVK_LeftArrow);
111 | qt_to_cg.insert(Qt::Key_Right, kVK_RightArrow);
112 | qt_to_cg.insert(Qt::Key_Down, kVK_DownArrow);
113 | qt_to_cg.insert(Qt::Key_Up, kVK_UpArrow);
114 | }
115 |
116 | void EventHandler::addMapping(int from, int to)
117 | {
118 | keyCodeMap.insert(from, to);
119 | }
120 |
121 | void EventHandler::mapToMouseButton(int mask, int button)
122 | {
123 | if(button == 1) {
124 | addMapping(mask, kCGEventRightMouseDown);
125 | }
126 | else if (button == 2) {
127 | addMapping(mask, kCGEventLeftMouseDown);
128 | }
129 | }
130 |
131 | void EventHandler::handleMouseMove(double dx, double dy){
132 | CGEventRef get = CGEventCreate(nullptr);
133 | CGPoint mouse = CGEventGetLocation(get);
134 |
135 | CGPoint pos;
136 | pos.x = mouse.x + dx;
137 | pos.y = mouse.y + dy;
138 |
139 | // see https://github.com/debauchee/barrier/blob/master/src/lib/platform/OSXScreen.mm
140 | // check if cursor position is valid on the client display configuration
141 | // stkamp@users.sourceforge.net
142 | CGDisplayCount displayCount = 0;
143 | CGGetDisplaysWithPoint(pos, 0, nullptr, &displayCount);
144 | if (displayCount == 0) {
145 | // cursor position invalid - clamp to bounds of last valid display.
146 | // find the last valid display using the last cursor position.
147 | displayCount = 0;
148 | CGDirectDisplayID displayID;
149 | CGGetDisplaysWithPoint(CGPointMake(mouse.x, mouse.y), 1,
150 | &displayID, &displayCount);
151 | if (displayCount != 0) {
152 | CGRect displayRect = CGDisplayBounds(displayID);
153 | if (pos.x < displayRect.origin.x) {
154 | pos.x = displayRect.origin.x;
155 | }
156 | else if (pos.x > displayRect.origin.x +
157 | displayRect.size.width - 1) {
158 | pos.x = displayRect.origin.x + displayRect.size.width - 1;
159 | }
160 | if (pos.y < displayRect.origin.y) {
161 | pos.y = displayRect.origin.y;
162 | }
163 | else if (pos.y > displayRect.origin.y +
164 | displayRect.size.height - 1) {
165 | pos.y = displayRect.origin.y + displayRect.size.height - 1;
166 | }
167 | }
168 | }
169 | CGEventType event_type = kCGEventMouseMoved;
170 | CGMouseButton button = kCGMouseButtonLeft;
171 | if(_left_button_down) {
172 | event_type = kCGEventLeftMouseDragged;
173 | }
174 | if(_right_button_down) {
175 | event_type = kCGEventRightMouseDragged;
176 | button = kCGMouseButtonRight;
177 | }
178 | CGEventRef mouseEv = CGEventCreateMouseEvent(
179 | nullptr, event_type,
180 | pos, button);
181 |
182 | double final_dx = pos.x - mouse.x;
183 | double final_dy = pos.y - mouse.y;
184 |
185 | CGEventSetIntegerValueField(mouseEv, kCGMouseEventDeltaX, (int)final_dx);
186 | CGEventSetIntegerValueField(mouseEv, kCGMouseEventDeltaY, (int)final_dy);
187 |
188 | CGEventSetDoubleValueField(mouseEv, kCGMouseEventDeltaX, final_dx);
189 | CGEventSetDoubleValueField(mouseEv, kCGMouseEventDeltaY, final_dy);
190 |
191 | CGEventPost(kCGHIDEventTap, mouseEv);
192 | CFRelease(mouseEv);
193 | }
194 |
195 | /*!
196 | * \brief EventHandler::handleButtonPress
197 | * \param button_mask
198 | */
199 | void EventHandler::handleButtonPress(int button_mask){
200 | // check if a mouse button is mapped to the button
201 | if(keyCodeMap.value(button_mask) == kCGEventLeftMouseDown){
202 |
203 | CGEventRef get = CGEventCreate(nullptr);
204 | CGPoint mouse = CGEventGetLocation(get);
205 | int64_t x = mouse.x;
206 | int64_t y = mouse.y;
207 |
208 | CGEventRef mouseEv1 = CGEventCreateMouseEvent(
209 | nullptr, kCGEventLeftMouseDown,
210 | CGPointMake(x, y),
211 | kCGMouseButtonLeft);
212 | CGEventPost(kCGHIDEventTap, mouseEv1);
213 | CFRelease(mouseEv1);
214 | _left_button_down = true;
215 | }
216 | else if(keyCodeMap.value(button_mask) == kCGEventRightMouseDown){
217 |
218 | CGEventRef get = CGEventCreate(nullptr);
219 | CGPoint mouse = CGEventGetLocation(get);
220 | int64_t x = mouse.x;
221 | int64_t y = mouse.y;
222 |
223 | CGEventRef mouseEv1 = CGEventCreateMouseEvent(
224 | nullptr, kCGEventRightMouseDown,
225 | CGPointMake(x, y),
226 | kCGMouseButtonLeft);
227 | CGEventPost(kCGHIDEventTap, mouseEv1);
228 | CFRelease(mouseEv1);
229 | _right_button_down = true;
230 | }
231 | // otherwise, get the key code value for the button
232 | else {
233 | int qt_key = keyCodeMap.value(button_mask, Qt::Key_Enter);
234 | unsigned short cg_key = qt_to_cg.value(qt_key);
235 | CGEventRef keyEvent = CGEventCreateKeyboardEvent( nullptr, cg_key, true ) ;
236 | CGEventPost( kCGHIDEventTap, keyEvent ) ;
237 | CFRelease( keyEvent ) ;
238 | }
239 | }
240 |
241 | void EventHandler::handleButtonRelease(int button_mask){
242 | if(keyCodeMap.value(button_mask) == kCGEventLeftMouseDown ){
243 |
244 | CGEventRef get = CGEventCreate(nullptr);
245 | CGPoint mouse = CGEventGetLocation(get);
246 | int64_t x = mouse.x;
247 | int64_t y = mouse.y;
248 |
249 | CGEventRef mouseEv2 = CGEventCreateMouseEvent(
250 | nullptr, kCGEventLeftMouseUp,
251 | CGPointMake(x, y),
252 | kCGMouseButtonLeft);
253 | CGEventPost(kCGHIDEventTap, mouseEv2);
254 | CFRelease(mouseEv2);
255 | _left_button_down = false;
256 | }
257 | if(keyCodeMap.value(button_mask) == kCGEventRightMouseDown ){
258 |
259 | CGEventRef get = CGEventCreate(nullptr);
260 | CGPoint mouse = CGEventGetLocation(get);
261 | int64_t x = mouse.x;
262 | int64_t y = mouse.y;
263 |
264 | CGEventRef mouseEv2 = CGEventCreateMouseEvent(
265 | nullptr, kCGEventRightMouseUp,
266 | CGPointMake(x, y),
267 | kCGMouseButtonLeft);
268 | CGEventPost(kCGHIDEventTap, mouseEv2);
269 | CFRelease(mouseEv2);
270 | _right_button_down = false;
271 | }
272 | else {
273 | int qt_key = keyCodeMap.value(button_mask, Qt::Key_Enter);
274 | unsigned short cg_key = qt_to_cg.value(qt_key);
275 | CGEventRef keyEvent = CGEventCreateKeyboardEvent( nullptr, cg_key, false ) ;
276 | CGEventPost( kCGHIDEventTap, keyEvent ) ;
277 | CFRelease( keyEvent ) ;
278 | }
279 | }
280 |
--------------------------------------------------------------------------------
/mac/powertools.h:
--------------------------------------------------------------------------------
1 | #ifndef POWERTOOLS_H
2 | #define POWERTOOLS_H
3 |
4 | #if !defined(__cplusplus)
5 | #define C_API extern
6 | #else
7 | #define C_API extern "C"
8 | #endif
9 |
10 | #include
11 |
12 | /* Power Tools
13 | * A few tools to control power management features in MacOS that
14 | * can cause problems with scientific applications. Designed for use with Qt.
15 | *
16 | * To use:
17 | * HEADERS += powertools.h
18 | * OBJECTIVE_SOURCES += powertools.mm
19 | * LIBS += -framework Foundation
20 | *
21 | * App Nap (timer coalescing, introduced in 10.9)
22 | * Disable App Nap if continued processing is needed
23 | * when the application is in the background
24 | * API from: https://developer.apple.com/documentation/foundation/nsprocessinfo
25 | * Based on the thread at: https://stackoverflow.com/questions/30686488/qapplication-is-lazy-or-making-other-threads-lazy-in-the-app
26 | *
27 | * User Sleep
28 | * Prevent the computer or display and computer from sleeping after
29 | * spending too long without user input
30 | * API from: https://developer.apple.com/documentation/iokit/iopmlib_h?language=objc
31 | *
32 | * License: MIT
33 | * Copyright 2019 Erik Werner
34 | * Permission is hereby granted, free of charge, to any person obtaining a copy
35 | * of this software and associated documentation files (the "Software"), to
36 | * deal in the Software without restriction, including without limitation the
37 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
38 | * sell copies of the Software, and to permit persons to whom the Software is
39 | * furnished to do so, subject to the following conditions:
40 |
41 | * The above copyright notice and this permission notice shall be included
42 | * in all copies or substantial portions of the Software.
43 |
44 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
45 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
46 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
47 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
48 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
49 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
50 | * DEALINGS IN THE SOFTWARE.
51 | */
52 |
53 |
54 | C_API void disableAppNap(const QString reason_string = "Disable App Nap");
55 | C_API void enableAppNap();
56 | C_API bool preventSleep(const QString assert_type = "PreventUserIdleDisplaySleep",
57 | const QString reason_string = "Program is running");
58 | C_API bool allowSleep();
59 |
60 | #endif // POWERTOOLS_H
61 |
--------------------------------------------------------------------------------
/mac/powertools.mm:
--------------------------------------------------------------------------------
1 | #include "powertools.h"
2 | #include // App Nap API
3 | #import // Power Management System API
4 |
5 | static id activity; //< keep track of the activity ID for app nap control
6 | static IOPMAssertionID assertionID; //< keep track of the assertion ID for sleep control
7 |
8 | /*!
9 | * \brief disableAppNap
10 | * \param reason_string a description of the activity preventing app nap. Used for debugging.
11 | */
12 | void disableAppNap(const QString reason_string) {
13 | NSString* nss = [[NSString alloc] initWithUTF8String:reason_string.toUtf8().data()];
14 | activity = [[NSProcessInfo processInfo] beginActivityWithOptions:NSActivityLatencyCritical | NSActivityUserInitiated
15 | reason:nss];
16 | }
17 |
18 | /*!
19 | * \brief enableAppNap
20 | */
21 | void enableAppNap() {
22 | [[NSProcessInfo processInfo] endActivity:activity];
23 | }
24 |
25 | /*!
26 | * \brief preventSleep
27 | * \param assert_type the assertion type to request from the power management system
28 | * Use "PreventUserIdleSystemSleep" to prevent system sleep, but allow display sleeping.
29 | * Use "PreventUserIdleDisplaySleep" to prevent both system and display sleeping (this is the default)
30 | * \param reason_string a string describing the activity preventing sleep. Max length is 128 characters
31 | * \return true if the assertion was successfully activated
32 | */
33 | bool preventSleep(const QString assert_type, const QString reason_string){
34 | CFStringRef reason_c = reason_string.toCFString();
35 | CFStringRef assertion_c = assert_type.toCFString();
36 | IOReturn success = IOPMAssertionCreateWithName(assertion_c,
37 | kIOPMAssertionLevelOn, reason_c, &assertionID);
38 | if (success == kIOReturnSuccess){
39 | return true;
40 | } else {
41 | return false;
42 | }
43 | }
44 |
45 | /*!
46 | * \brief allowSleep
47 | * \return true if the assertio was successfully released
48 | */
49 | bool allowSleep(){
50 | IOReturn success = IOPMAssertionRelease(assertionID);
51 | if (success == kIOReturnSuccess){
52 | return true;
53 | } else {
54 | return false;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/main.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.h"
2 | #include "powertools.h"
3 | #include
4 |
5 | #ifndef QT_NO_SYSTEMTRAYICON
6 |
7 | #include
8 |
9 | int main(int argc, char *argv[])
10 | {
11 | int id1 = qRegisterMetaType >();
12 | int id2 = qRegisterMetaType >();
13 | int id3 = qRegisterMetaType >();
14 | int id4 = qRegisterMetaType();
15 |
16 | Q_INIT_RESOURCE(resources);
17 | QApplication a(argc, argv);
18 | disableAppNap();
19 | if (!QSystemTrayIcon::isSystemTrayAvailable()) {
20 | QMessageBox::critical(nullptr, QObject::tr("Systray"),
21 | QObject::tr("Unable to detect a system tray "
22 | "on this system."));
23 | return 1;
24 | }
25 | QApplication::setQuitOnLastWindowClosed(false);
26 | MainWindow w;
27 |
28 | w.show();
29 |
30 | int code = a.exec();
31 | enableAppNap();
32 | return code;
33 | }
34 |
35 | #else
36 |
37 | #include
38 | #include
39 |
40 | int main(int argc, char *argv[])
41 | {
42 | QApplication app(argc, argv);
43 | QString text("QSystemTrayIcon is not supported on this platform");
44 |
45 | QLabel *label = new QLabel(text);
46 | label->setWordWrap(true);
47 |
48 | label->show();
49 | qDebug() << text;
50 |
51 | app.exec();
52 | }
53 |
54 | #endif
55 |
--------------------------------------------------------------------------------
/mainwindow.h:
--------------------------------------------------------------------------------
1 | #ifndef MAINWINDOW_H
2 | #define MAINWINDOW_H
3 |
4 | #include
5 | #include
6 |
7 | #include "joyconworker.h"
8 |
9 | // https://stackoverflow.com/questions/40599038/on-linux-whats-a-good-way-to-to-use-hid-reports-over-usb
10 |
11 | class QThread;
12 | class StatusWidget;
13 | class InputMapWidget;
14 |
15 | namespace Ui {
16 | class MainWindow;
17 | }
18 |
19 | /*!
20 | * \brief The MainWindow class is the root of the QJoyControl GUI.
21 | * It can be shown or hidden, but it will remain alive until the application
22 | * is closed.
23 | */
24 | class MainWindow : public QMainWindow
25 | {
26 | Q_OBJECT
27 |
28 | public:
29 | /*!
30 | * \brief MainWindow default constructor
31 | * \param parent usually a nullptr
32 | */
33 | explicit MainWindow(QWidget *parent = nullptr);
34 | ~MainWindow() override;
35 |
36 | protected:
37 | void closeEvent(QCloseEvent *event) override;
38 | void resizeEvent(QResizeEvent *event) override;
39 |
40 | public slots:
41 | void onShow();
42 | void onHide();
43 |
44 | void onCameraImageData(QImage img);
45 | void hideAndClose();
46 |
47 | void onNewInputData(QList button_data, QList analog_data);
48 | void onDeviceConnectionChanged(QString sn, const unsigned short pid);
49 | void onJoyConStatusMessage(QString message);
50 |
51 | signals:
52 | void connectHID(unsigned short vendor_id,
53 | unsigned short product_id,
54 | const wchar_t *serial_number);
55 |
56 | void disconnectHID();
57 |
58 | void enableInputStreaming(bool);
59 |
60 | void updateIrConfig(ir_image_config);
61 | void captureImage(unsigned char);
62 |
63 | private slots:
64 | void onDeviceInfoData(QList device_info, int joycon_type);
65 | void onTemperatureData(float temp_c);
66 | void onBatteryData(int volt, int percent, int status);
67 |
68 | void on_pushButtonCapture_clicked();
69 | void on_pushButtonStream_clicked();
70 |
71 | void on_checkBoxDiagnostics_toggled(bool checked);
72 | void on_checkBoxAppNap_toggled(bool checked);
73 | void on_checkBoxIdleSleep_toggled(bool checked);
74 |
75 | void on_toolButtonRefresh_clicked();
76 | void on_toolButtonConnect_clicked();
77 | void on_toolButtonDisconnect_clicked();
78 |
79 | void on_checkBoxInvertIcon_toggled(bool checked);
80 |
81 | void on_pushButtonSaveImage_clicked();
82 |
83 | void on_comboBoxColorMap_currentIndexChanged(int index);
84 |
85 | void showAbout();
86 |
87 | void on_checkBoxLeftClick_toggled(bool checked);
88 |
89 | void on_checkBoxRightClick_toggled(bool checked);
90 |
91 | private:
92 | Ui::MainWindow *ui;
93 | StatusWidget* _status_widget;
94 | EventHandler* _event_handler = nullptr;
95 | QSystemTrayIcon *_tray_icon = nullptr;
96 | QMenu *_tray_icon_menu;
97 | JoyConWorker* _worker;
98 | QThread* _thread;
99 |
100 | QAction *_hide_action;
101 | QAction *_show_action;
102 | QAction *_about_action;
103 | QAction *_quit_action;
104 |
105 | bool _force_close = false;
106 |
107 | unsigned short _joycon_pid = 0;
108 | QString _joycon_sn = QString();
109 | // hold the last button state received
110 | int _last_button_state[3] = {0,0,0};
111 | QImage _current_image = QImage();
112 | QVector _color_table;
113 | InputMapWidget* _l_mapper = nullptr;
114 | InputMapWidget* _zl_mapper = nullptr;
115 | InputMapWidget* _r_mapper = nullptr;
116 | InputMapWidget* _zr_mapper = nullptr;
117 |
118 | qint64 _time_last_update; // keep track of the last time the GUI was updated
119 |
120 |
121 | void loadSettings();
122 | void setupThread();
123 | void addHidItem(struct hid_device_info* info);
124 | void sendCameraConfig();
125 | void saveSettings();
126 | void handleButtons(QList buttons);
127 | double scaleAnalog(double input);
128 | void createTrayIcon(bool is_inverted);
129 | void testButton(int last_button_state, int _last_button_state, int mask);
130 | };
131 |
132 | #endif // MAINWINDOW_H
133 |
--------------------------------------------------------------------------------
/resources.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | img/batt_0.png
4 | img/batt_0_chr.png
5 | img/batt_100.png
6 | img/batt_100_chr.png
7 | img/batt_25.png
8 | img/batt_25_chr.png
9 | img/batt_50.png
10 | img/batt_50_chr.png
11 | img/batt_75.png
12 | img/batt_75_chr.png
13 | img/retail_colors.xml
14 | img/Logo.icns
15 | img/Logo.png
16 | img/Logo.svg
17 |
18 |
19 |
--------------------------------------------------------------------------------
/statuswidget.cpp:
--------------------------------------------------------------------------------
1 | #include "statuswidget.h"
2 | #include "ui_statuswidget.h"
3 | #include
4 | #include
5 |
6 | StatusWidget::StatusWidget(QWidget *parent) :
7 | QWidget(parent),
8 | ui(new Ui::StatusWidget),
9 | _battery_pixmap(QPixmap())
10 | {
11 | ui->setupUi(this);
12 | }
13 |
14 | StatusWidget::~StatusWidget()
15 | {
16 | delete ui;
17 | }
18 |
19 | void StatusWidget::onBatteryData(int batt, QString text){
20 | ui->labelBatteryText->setText(text);
21 |
22 | // Update Battery icon from input report value.
23 | switch (batt) {
24 | case 0:
25 | _battery_pixmap.load(":/img/batt_0.png");
26 | break;
27 | case 1:
28 | _battery_pixmap.load(":/img/batt_0_chr.png");
29 | break;
30 | case 2:
31 | _battery_pixmap.load(":/img/batt_25.png");
32 | break;
33 | case 3:
34 | _battery_pixmap.load(":/img/batt_25_cr.png");
35 | break;
36 | case 4:
37 | _battery_pixmap.load(":/img/batt_50.png");
38 | break;
39 | case 5:
40 | _battery_pixmap.load(":/img/batt_50_cr.png");
41 | break;
42 | case 6:
43 | _battery_pixmap.load(":/img/batt_75.png");
44 | break;
45 | case 7:
46 | _battery_pixmap.load(":/img/batt_75_cr.png");
47 | break;
48 | case 8:
49 | _battery_pixmap.load(":/img/batt_100.png");
50 | break;
51 | case 9:
52 | _battery_pixmap.load(":/img/batt_100_cr.png");
53 | break;
54 | default:
55 | _battery_pixmap.load(":/img/batt_0.png");
56 | }
57 |
58 | ui->labelBatteryGraphic->setPixmap(_battery_pixmap.scaled(24,9));
59 | }
60 |
61 | void StatusWidget::onTemperatureData(float temp){
62 | QString text_string("Temp: ");
63 | text_string += QString::number(temp, 'f', 1);
64 | text_string +=("ºC ");
65 | ui->labelTempText->setText(text_string);
66 | }
67 |
--------------------------------------------------------------------------------
/statuswidget.h:
--------------------------------------------------------------------------------
1 | #ifndef STATUSWIDGET_H
2 | #define STATUSWIDGET_H
3 |
4 | #include
5 |
6 | namespace Ui {
7 | class StatusWidget;
8 | }
9 |
10 | class StatusWidget : public QWidget
11 | {
12 | Q_OBJECT
13 |
14 | public:
15 | explicit StatusWidget(QWidget *parent = nullptr);
16 | ~StatusWidget();
17 |
18 | public slots:
19 | void onBatteryData(int batt, QString text);
20 | void onTemperatureData(float temp);
21 | private:
22 | Ui::StatusWidget *ui;
23 | QPixmap _battery_pixmap;
24 | };
25 |
26 | #endif // STATUSWIDGET_H
27 |
--------------------------------------------------------------------------------
/statuswidget.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | StatusWidget
4 |
5 |
6 |
7 | 0
8 | 0
9 | 439
10 | 38
11 |
12 |
13 |
14 | Form
15 |
16 |
17 |
18 |
19 |
20 | -
21 |
22 |
23 |
24 |
25 |
26 |
27 | -
28 |
29 |
30 |
31 |
32 |
33 |
34 | -
35 |
36 |
37 |
38 | 0
39 | 0
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------