├── AddIns
├── spconvd
│ ├── .gitignore
│ ├── Makefile
│ ├── readme.txt
│ └── main.c
├── SpaceMouse
│ ├── SpaceMouse.manifest
│ └── SpaceMouse.py
└── README.md
├── siappdll.dll
├── siappdll
├── src
│ ├── log.cpp
│ ├── config.h
│ ├── sock.h
│ ├── sock_ll.h
│ ├── log.h
│ ├── siappdll_impl.h
│ ├── sock.cpp
│ ├── sock_ll.asm
│ ├── siappdll.h
│ ├── syncapi.h
│ ├── sidef.h
│ ├── syncapi.cpp
│ └── siappdll.cpp
├── x64
│ └── Release
│ │ └── siappdll.dll
├── packages.config
├── siappdll.sln
├── siappdll.def
├── siappdll.vcxproj.filters
├── .gitignore
├── siappdll.vcproj
└── siappdll.vcxproj
├── win_dll_test
├── siappdll.dll
└── jet.exe
└── README.md
/AddIns/spconvd/.gitignore:
--------------------------------------------------------------------------------
1 | spconvd
2 |
--------------------------------------------------------------------------------
/siappdll.dll:
--------------------------------------------------------------------------------
1 | siappdll/x64/Release/siappdll.dll
--------------------------------------------------------------------------------
/siappdll/src/log.cpp:
--------------------------------------------------------------------------------
1 | #include "log.h"
2 |
3 | Logger logger;
--------------------------------------------------------------------------------
/win_dll_test/siappdll.dll:
--------------------------------------------------------------------------------
1 | ../siappdll/x64/Release/siappdll.dll
--------------------------------------------------------------------------------
/AddIns/spconvd/Makefile:
--------------------------------------------------------------------------------
1 | all:
2 | gcc main.c -o spconvd
3 | install:
4 | cp spconvd ~/.local/bin/
5 |
--------------------------------------------------------------------------------
/win_dll_test/jet.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DD1984/SpaceMouse_Fusion360_Wine/HEAD/win_dll_test/jet.exe
--------------------------------------------------------------------------------
/AddIns/spconvd/readme.txt:
--------------------------------------------------------------------------------
1 | build: make && make install
2 | spconvd will be installed to ~/.local/bin/
3 |
4 |
--------------------------------------------------------------------------------
/siappdll/x64/Release/siappdll.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DD1984/SpaceMouse_Fusion360_Wine/HEAD/siappdll/x64/Release/siappdll.dll
--------------------------------------------------------------------------------
/siappdll/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/siappdll/src/config.h:
--------------------------------------------------------------------------------
1 | #ifndef CONFIG_H_
2 | #define CONFIG_H_
3 |
4 | #define VER_MAJOR 17
5 | #define VER_MINOR 2
6 | #define VER_BUILD 14205
7 | #define VER_STR "fake 3dxsrv/siappdll"
8 |
9 | #endif /* CONFIG_H_ */
--------------------------------------------------------------------------------
/AddIns/SpaceMouse/SpaceMouse.manifest:
--------------------------------------------------------------------------------
1 | {
2 | "autodeskProduct": "Fusion360",
3 | "type": "addin",
4 | "id": "6b509eec-34ca-4044-875d-cfb30563b658",
5 | "author": "",
6 | "description": {
7 | "": "Creates a spur gear component."
8 | },
9 | "version": "",
10 | "runOnStartup": false,
11 | "supportedOS": "windows|mac",
12 | "editEnabled": true
13 | }
--------------------------------------------------------------------------------
/siappdll/src/sock.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define SOCK_FILE "/var/run/spnav.sock"
4 |
5 | #define AF_UNIX 1
6 | #define SOCK_STREAM 1
7 |
8 | struct sockaddr_un {
9 | unsigned short sun_family; /* AF_UNIX */
10 | char sun_path[108]; /* pathname */
11 | };
12 |
13 | int sock_connect(const char* sock_file);
14 | int sock_read(int fd, char* buf, size_t count);
15 | void sock_close(int fd);
--------------------------------------------------------------------------------
/siappdll/src/sock_ll.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | extern "C" int __fastcall l_open(const char* filename, int flags, int mode);
4 | extern "C" int __fastcall l_read(int fd, char* buf, unsigned int count);
5 | extern "C" int __fastcall l_close(int fd);
6 | extern "C" int __fastcall l_socket(int domain, int type, int protocol);
7 | extern "C" int __fastcall l_connect(int sockfd, const struct sockaddr* addr, unsigned int addrlen);
8 |
9 | extern "C" int __fastcall l_socket_int80h(int domain, int type, int protocol);
10 | extern "C" int __fastcall l_connect_int80h(int sockfd, const struct sockaddr* addr, unsigned int addrlen);
11 | extern "C" int __fastcall l_read_int80h(int fd, char* buf, unsigned int count);
12 | extern "C" int __fastcall l_close_int80h(int fd);
13 |
--------------------------------------------------------------------------------
/siappdll/src/log.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | enum class DbgType {
10 | INFO_T = 0,
11 | ERROR_T,
12 | TRACE_T,
13 | };
14 |
15 | class Logger
16 | {
17 | using Stream = std::ostringstream;
18 | using Buffer_p = std::unique_ptr>;
19 |
20 | public:
21 | void log(const std::string& cmd) {
22 | std::cout << cmd << std::endl;
23 | }
24 |
25 | Buffer_p log(DbgType l) {
26 | return Buffer_p(new Stream, [&, this, l](Stream* st) {
27 | if (l <= dbgLevel)
28 | log(st->str());
29 | });
30 | }
31 |
32 | private:
33 | DbgType dbgLevel = DbgType::ERROR_T;
34 | };
35 |
36 | extern Logger logger;
37 |
38 | #define LOG(x) *(logger.log(DbgType:: ## x ## _T)) << "[*** SPMOUSE ***] " << #x << " "
39 |
--------------------------------------------------------------------------------
/siappdll/src/siappdll_impl.h:
--------------------------------------------------------------------------------
1 | /*
2 | SpaceNavigatorEmulator - 3dconnexion-compatible siappdll.dll replacement
3 | Copyright (C) 2014 John Tsiombikas
4 | Copyright (C) 2015 Luke Nuttall
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 | #pragma once
20 | #ifndef __SIAPPDLL_IMPL_H__
21 | #define __SIAPPDLL_IMPL_H__
22 |
23 | #include
24 |
25 | extern "C" {
26 |
27 | struct SiHdl {
28 | SiOpenData opendata;
29 | // SpaceNavigatorEmulator::SpaceNavConnector* connector;
30 | };
31 |
32 | unsigned int space_ware_message;
33 |
34 | bool initialised = false;
35 | }
36 | #endif
37 |
--------------------------------------------------------------------------------
/siappdll/siappdll.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.1.32228.430
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "siappdll", "siappdll.vcxproj", "{E3AE0F7F-2BBD-4563-AE22-1A92E11630F0}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Profile|x64 = Profile|x64
12 | Release|x64 = Release|x64
13 | EndGlobalSection
14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
15 | {E3AE0F7F-2BBD-4563-AE22-1A92E11630F0}.Debug|x64.ActiveCfg = Debug|x64
16 | {E3AE0F7F-2BBD-4563-AE22-1A92E11630F0}.Debug|x64.Build.0 = Debug|x64
17 | {E3AE0F7F-2BBD-4563-AE22-1A92E11630F0}.Profile|x64.ActiveCfg = Release|Win32
18 | {E3AE0F7F-2BBD-4563-AE22-1A92E11630F0}.Release|x64.ActiveCfg = Release|x64
19 | {E3AE0F7F-2BBD-4563-AE22-1A92E11630F0}.Release|x64.Build.0 = Release|x64
20 | EndGlobalSection
21 | GlobalSection(SolutionProperties) = preSolution
22 | HideSolutionNode = FALSE
23 | EndGlobalSection
24 | GlobalSection(ExtensibilityGlobals) = postSolution
25 | SolutionGuid = {43BB3D89-917B-413A-84C4-584E2EC97223}
26 | EndGlobalSection
27 | EndGlobal
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | **if something does not work - pls, use development wine branch, in staging branch "ntdll-Syscall_Emulation" feature is enabled - and this feature prevent to use direct linux syscalls execution, whitch using by this dll to access to driver unix socket, but dll have workaround solution - int80h api - and it is workable in my tests on wine-9.0-rc2 (Staging)**
2 |
3 | This is new solution to make 3Dconnexion SpaceMouse workable in Fusion 360 in Linux under WINE (other applications may work too)
4 | New solution based on dll replacment and work together with open source linux driver for space mouse [spacenavd](http://spacenav.sourceforge.net/),
5 | [old](https://github.com/DD1984/SpaceMouse_Fusion360_Wine/tree/master/AddIns) solution - based on AddIns
6 |
7 |
8 | #### instalation:
9 | * **spacenavd** must be installed first from you distributive repositories
10 | * copy **siappdll.dll** to the folder of your program (folder where Fusion360.exe placed)
11 | * setup **_legacy_** SpaceMouse driver in Fusion 360 *Preferences*
12 | * **spnavcfg** could be installed - this is graphical util for fine tune space mouse parameters (this package do not exist in ubuntu repos, but you could download it from spacenavd website)
13 |
14 | #### TODO:
15 | * [ ] Buttons
16 | * [ ] CPU load
17 |
18 | #### Very Thanks:
19 | * [SpaceNavigatorEmulator](https://github.com/lukenuttall/SpaceNavigatorEmulator)
20 | * [wine-discord-ipc-bridge](https://github.com/0e4ef622/wine-discord-ipc-bridge)
21 |
--------------------------------------------------------------------------------
/AddIns/README.md:
--------------------------------------------------------------------------------
1 | This is workaround solution to make 3Dconnexion SpaceMouse workable in Fusion 360 in Linux under WINE - [video](https://youtu.be/KpPamemM14c)
2 | #### how it work:
3 | solution consist from two part:
4 | * spconvd - daemon that connect to [spacenavd](http://spacenav.sourceforge.net/) (open source linux driver for spacemouse), read mouse events and then send it to Fusion 360 via network through *localhost:11111*
5 | * AddIns (plugin) for Fusion 360, that read mouse events from spconvd and convert it to camera motions using Fusion 360 API
6 | #### instalation:
7 | * **spacenavd** must be installed first from you distributive repositories (this package exist in Ubuntu 21.04 repos)
8 | * **spnavcfg** could be installed - this is graphical util for fine tune space mouse parameters (this package do not exist in ubuntu repos, but you could download it from spacenavd website)
9 | * clone this repo, go to spconvd directory and execute: ```make && make install``` - this will build and install spconvd daemon to ```~/.local/bin/```
10 | * run spconvd **manually**
11 | * copy **SpaceMouse** folder into Fusion 360 AddIns path: ```~/.wine/drive_c/users//Application Data/Autodesk/Autodesk Fusion 360/API/AddIns```
12 | * start Fusion 360, go to AddIns menu and **Run** SpaceMouse - that is all
13 | * #### TODO:
14 | * - [ ] move mouse events shaper(it need to decrease cpu load by decrease screen refresh rate) from spconvd to AddIns
15 | * - [ ] rewrite spconvd on python
16 | * - [ ] fine tune coefficients of motions, rotations and zoom
17 |
--------------------------------------------------------------------------------
/siappdll/siappdll.def:
--------------------------------------------------------------------------------
1 | LIBRARY "siappdll"
2 |
3 | EXPORTS
4 | SpwErrorVal
5 |
6 | SiInitialize
7 | SiIsInitialized
8 | SiTerminate
9 |
10 | SiGetLibraryInfo
11 | SiGetDriverInfo
12 | SiGetDevicePort
13 |
14 | SiGetNumDevices
15 | SiDeviceIndex
16 |
17 | SiOpenWinInit
18 | SiOpen
19 | SiOpenPort
20 | SiClose
21 |
22 | SiGetDeviceID
23 | SiGetDeviceImageFileName
24 | SiGetDeviceInfo
25 | SiGetDeviceName
26 |
27 | SiGrabDevice
28 | SiReleaseDevice
29 |
30 | SiRezero
31 | SiBeep
32 | SiSetLEDs
33 | SiSetUiMode
34 |
35 | SiDispatch
36 |
37 | SiGetEventWinInit
38 | SiGetEvent
39 | SiPeekEvent
40 |
41 | SiIsSpaceWareEvent
42 | SiButtonPressed
43 | SiButtonReleased
44 | SiGetButtonName
45 |
46 | SiSyncSendQuery
47 | SiSyncGetVersion
48 | SiSyncGetNumberOfFunctions
49 | SiSyncGetFunction
50 | SiSyncGetButtonAssignment
51 | SiSyncSetButtonAssignment
52 | SiSyncSetButtonAssignmentAbsolute
53 | SiSyncSetButtonName
54 | SiSyncGetAxisLabel
55 | SiSyncSetAxisLabel
56 | SiSyncGetOrientation
57 | SiSyncSetOrientation
58 | SiSyncGetFilter
59 | SiSyncSetFilter
60 | SiSyncGetAxesState
61 | SiSyncSetAxesState
62 | SiSyncSetInfoLine
63 | SiSyncGetScaleOverall
64 | SiSyncSetScaleOverall
65 | SiSyncGetScaleTx
66 | SiSyncSetScaleTx
67 | SiSyncGetScaleTy
68 | SiSyncSetScaleTy
69 | SiSyncGetScaleTz
70 | SiSyncSetScaleTz
71 | SiSyncGetScaleRx
72 | SiSyncSetScaleRx
73 | SiSyncGetScaleRy
74 | SiSyncSetScaleRy
75 | SiSyncGetScaleRz
76 | SiSyncSetScaleRz
77 | SiSyncInvokeAbsoluteFunction
78 | SiSyncSetButtonState
79 |
80 | SiGetCompanyIcon
81 | SiGetCompanyLogoFileName
82 |
83 | SpwErrorString
84 |
85 | SiSetTypeMask
--------------------------------------------------------------------------------
/siappdll/src/sock.cpp:
--------------------------------------------------------------------------------
1 | #include "sock_ll.h"
2 | #include "sock.h"
3 | #include "log.h"
4 |
5 | bool int80h = false;
6 |
7 | int sock_connect(const char *sock_file)
8 | {
9 | LOG(INFO) << "Creating socket";
10 |
11 | int fd = -1;
12 | if (int80h || (fd = l_socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
13 | LOG(ERROR) << "l_socket() return err: 0x" << std::hex << fd;
14 |
15 | /* workaround because l_socket() sometime return strange 0xc0000002 value */
16 | LOG(INFO) << "trying l_socket_int80h()";
17 | fd = l_socket_int80h(AF_UNIX, SOCK_STREAM, 0);
18 | if (fd < 0) {
19 | LOG(ERROR) << "l_socket_int80h() return err: 0x" << std::hex << fd;
20 | LOG(ERROR) << "Failed to create socket";
21 | return -1;
22 | }
23 |
24 | LOG(INFO) << "Using int80h api!!!";
25 | int80h = true;
26 | }
27 |
28 | LOG(INFO) << "fd: " << fd;
29 |
30 | struct sockaddr_un addr;
31 | addr.sun_family = AF_UNIX;
32 | snprintf(addr.sun_path, sizeof(addr.sun_path), sock_file);
33 |
34 | LOG(INFO) << "Attempting to connect to " << addr.sun_path;
35 |
36 | int (*connect_func)(int sockfd, const struct sockaddr* addr, unsigned int addrlen) = l_connect;
37 | if (int80h)
38 | connect_func = l_connect_int80h;
39 |
40 | int ret;
41 | if ((ret = connect_func(fd, (struct sockaddr*)&addr, sizeof(addr))) < 0) {
42 | LOG(ERROR) << "connect() return err: 0x" << std::hex << ret;
43 | LOG(ERROR) << "Failed to connect";
44 |
45 | sock_close(fd);
46 | return -1;
47 | }
48 |
49 | return fd;
50 | }
51 |
52 | int sock_read(int fd, char* buf, size_t count)
53 | {
54 | int (*read_func)(int fd, char* buf, unsigned int count) = l_read;
55 | if (int80h)
56 | read_func = l_read_int80h;
57 |
58 | return read_func(fd, buf, count);
59 | }
60 |
61 | void sock_close(int fd)
62 | {
63 | int (*close_func)(int fd) = l_close;
64 | if (int80h)
65 | close_func = l_close_int80h;
66 |
67 | close_func(fd);
68 | }
--------------------------------------------------------------------------------
/siappdll/siappdll.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 | Source Files
23 |
24 |
25 | Source Files
26 |
27 |
28 | Source Files
29 |
30 |
31 |
32 |
33 | Source Files
34 |
35 |
36 |
37 |
38 |
39 | Header Files
40 |
41 |
42 | Header Files
43 |
44 |
45 | Header Files
46 |
47 |
48 | Header Files
49 |
50 |
51 | Header Files
52 |
53 |
54 | Header Files
55 |
56 |
57 | Header Files
58 |
59 |
60 | Header Files
61 |
62 |
63 |
64 |
65 | Source Files
66 |
67 |
68 |
--------------------------------------------------------------------------------
/siappdll/src/sock_ll.asm:
--------------------------------------------------------------------------------
1 | .data
2 |
3 | .code
4 | ALIGN 16
5 |
6 | ;RCX, b in RDX, c in R8
7 | ; https://learn.microsoft.com/en-us/cpp/build/x64-software-conventions?view=msvc-170#x64-register-usage
8 | ; https://syscall.sh/
9 |
10 | l_open PROC
11 | sub rsp, 28h ; shadow stack
12 |
13 | push rdi
14 | push rsi
15 |
16 | mov rax, 2
17 |
18 | mov rdi, rcx
19 | mov rsi, rdx
20 | mov rdx, r8
21 |
22 | syscall
23 |
24 | pop rsi
25 | pop rdi
26 |
27 | add rsp, 28h ; restoring shadow stack
28 | ret
29 | l_open ENDP
30 |
31 | l_read PROC
32 | sub rsp, 28h ; shadow stack
33 |
34 | push rdi
35 | push rsi
36 |
37 | mov rax, 0
38 |
39 | mov rdi, rcx
40 | mov rsi, rdx
41 | mov rdx, r8
42 |
43 | syscall
44 |
45 | pop rsi
46 | pop rdi
47 |
48 | add rsp, 28h ; restoring shadow stack
49 | ret
50 | l_read ENDP
51 |
52 | l_read_int80h PROC
53 | sub rsp, 28h ; shadow stack
54 |
55 | push rbx
56 |
57 | mov rax, 3
58 | mov rbx, rcx
59 | mov rcx, rdx
60 | mov rdx, r8
61 | int 80h
62 |
63 | pop rbx
64 |
65 | add rsp, 28h ; restoring shadow stack
66 | ret
67 | l_read_int80h ENDP
68 |
69 | l_close PROC
70 | sub rsp, 28h ; shadow stack
71 |
72 | push rdi
73 |
74 | mov rax, 3
75 |
76 | mov rdi, rcx
77 |
78 | syscall
79 |
80 | pop rdi
81 |
82 | add rsp, 28h ; restoring shadow stack
83 | ret
84 | l_close ENDP
85 |
86 | l_close_int80h PROC
87 | sub rsp, 28h ; shadow stack
88 |
89 | push rbx
90 |
91 | mov rax, 6
92 | mov rbx, rcx
93 | int 80h
94 |
95 | pop rbx
96 |
97 | add rsp, 28h ; restoring shadow stack
98 | ret
99 | l_close_int80h ENDP
100 |
101 | l_socket PROC
102 | sub rsp, 28h ; shadow stack
103 |
104 | push rdi
105 | push rsi
106 |
107 | mov rax, 41
108 |
109 | mov rdi, rcx
110 | mov rsi, rdx
111 | mov rdx, r8
112 |
113 | syscall
114 |
115 | pop rsi
116 | pop rdi
117 |
118 | add rsp, 28h ; restoring shadow stack
119 | ret
120 | l_socket ENDP
121 |
122 | l_socket_int80h PROC
123 | sub rsp, 28h ; shadow stack
124 |
125 | push rbx
126 |
127 | mov eax, 359
128 | mov ebx, ecx
129 | mov ecx, edx
130 | mov edx, r8d
131 | int 80h
132 |
133 | pop rbx
134 |
135 | add rsp, 28h ; restoring shadow stack
136 | ret
137 | l_socket_int80h ENDP
138 |
139 | l_connect PROC
140 | sub rsp, 28h ; shadow stack
141 |
142 | push rdi
143 | push rsi
144 |
145 | mov rax, 42
146 |
147 | mov rdi, rcx
148 | mov rsi, rdx
149 | mov rdx, r8
150 |
151 | syscall
152 |
153 | pop rsi
154 | pop rdi
155 |
156 | add rsp, 28h ; restoring shadow stack
157 | ret
158 | l_connect ENDP
159 |
160 | l_connect_int80h PROC
161 | sub rsp, 28h ; shadow stack
162 |
163 | push rbx
164 |
165 | mov rax, 362
166 | mov rbx, rcx
167 | mov rcx, rdx
168 | mov rdx, r8
169 | int 80h
170 |
171 | pop rbx
172 |
173 | add rsp, 28h ; restoring shadow stack
174 | ret
175 | l_connect_int80h ENDP
176 |
177 | END
--------------------------------------------------------------------------------
/siappdll/src/siappdll.h:
--------------------------------------------------------------------------------
1 | /*
2 | SpaceNavigatorEmulator - 3dconnexion-compatible siappdll.dll replacement
3 | Copyright (C) 2014 John Tsiombikas
4 | Copyright (C) 2015 Luke Nuttall
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 | #pragma once
20 |
21 | #include "sidef.h"
22 |
23 | enum SpwRetVal SpwErrorVal;
24 |
25 | #ifdef __cplusplus
26 | extern "C" {
27 | #endif
28 |
29 | int _afxForceUSRDLL;
30 |
31 | BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved);
32 |
33 | enum SpwRetVal SPWAPI SiInitialize(void);
34 | SPWbool SiIsInitialized();
35 | void SPWAPI SiTerminate(void);
36 |
37 | void SPWAPI SiGetLibraryInfo(SiVerInfo *info);
38 | enum SpwRetVal SPWAPI SiGetDriverInfo(SiVerInfo *info);
39 | enum SpwRetVal SPWAPI SiGetDevicePort(int devid, SiDevPort *port);
40 |
41 | int SPWAPI SiGetNumDevices(void);
42 |
43 | void SPWAPI SiOpenWinInit(SiOpenData *opendata, void *win);
44 | struct SiHdl *SPWAPI SiOpen(const char *appname, int devid, SiTypeMask *tmask, int mode, SiOpenData *opendata);
45 | struct SiHdl* SPWAPI SiOpenPort(const char *pAppName, const SiDevPort *pPort, int mode, const SiOpenData *pData);
46 | enum SpwRetVal SPWAPI SiClose(struct SiHdl *si);
47 |
48 | int SPWAPI SiGetDeviceID(struct SiHdl *si);
49 | enum SpwRetVal SPWAPI SiGetDeviceImageFileName(struct SiHdl *si, char *name, unsigned long *maxlen);
50 | enum SpwRetVal SPWAPI SiGetDeviceInfo(struct SiHdl *si, SiDevInfo *info);
51 | enum SpwRetVal SPWAPI SiGetDeviceName(struct SiHdl *si, SiDeviceName *name);
52 |
53 | enum SpwRetVal SPWAPI SiGrabDevice(struct SiHdl *si, SPWbool exclusive);
54 | enum SpwRetVal SPWAPI SiReleaseDevice(struct SiHdl *si);
55 |
56 | enum SpwRetVal SPWAPI SiRezero(struct SiHdl *si);
57 | enum SpwRetVal SPWAPI SiBeep(struct SiHdl *si, char *str);
58 | enum SpwRetVal SPWAPI SiSetLEDs(struct SiHdl *si, unsigned long mask);
59 | enum SpwRetVal SPWAPI SiSetUiMode(struct SiHdl *si, unsigned long mode);
60 |
61 | int SPWAPI SiDispatch(struct SiHdl *si, SiGetEventData *data, SiSpwEvent *ev, SiSpwHandlers *handlers);
62 |
63 | void SPWAPI SiGetEventWinInit(SiGetEventData *evdata, unsigned int msg, unsigned int wparam, long lparam);
64 | SpwRetVal SPWAPI SiGetEvent(struct SiHdl *si, int flags, const SiGetEventData *data, SiSpwEvent *ev);
65 | SpwRetVal SPWAPI SiPeekEvent(struct SiHdl *si, int flags, const SiGetEventData *data, SiSpwEvent *ev);
66 |
67 | int SPWAPI SiButtonPressed(SiSpwEvent *ev);
68 | int SPWAPI SiButtonReleased(SiSpwEvent *ev);
69 | enum SpwRetVal SPWAPI SiGetButtonName(struct SiHdl *si, unsigned long bnum, SiButtonName *name);
70 |
71 | void *SPWAPI SiGetCompanyIcon(void);
72 | enum SpwRetVal SPWAPI SiGetCompanyLogoFileName(char *name, unsigned long *maxlen);
73 |
74 | const char *SPWAPI SpwErrorString(enum SpwRetVal err);
75 |
76 |
77 |
78 | /* deprecated */
79 | enum SpwRetVal SiSetTypeMask(SiTypeMask *mask, int type1, ...);
80 |
81 | #include "syncapi.h"
82 |
83 | #ifdef __cplusplus
84 | }
85 | #endif
86 |
87 |
--------------------------------------------------------------------------------
/siappdll/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/**/*
19 | x86/
20 | build/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studo 2015 cache/options directory
26 | .vs/
27 |
28 | # MSTest test Results
29 | [Tt]est[Rr]esult*/
30 | [Bb]uild[Ll]og.*
31 |
32 | # NUNIT
33 | *.VisualState.xml
34 | TestResult.xml
35 |
36 | # Build Results of an ATL Project
37 | [Dd]ebugPS/
38 | [Rr]eleasePS/
39 | dlldata.c
40 |
41 | # DNX
42 | project.lock.json
43 | artifacts/
44 |
45 | *_i.c
46 | *_p.c
47 | *_i.h
48 | *.ilk
49 | *.meta
50 | *.obj
51 | *.pch
52 | *.pdb
53 | *.pgc
54 | *.pgd
55 | *.rsp
56 | *.sbr
57 | *.tlb
58 | *.tli
59 | *.tlh
60 | *.tmp
61 | *.tmp_proj
62 | *.log
63 | *.vspscc
64 | *.vssscc
65 | .builds
66 | *.pidb
67 | *.svclog
68 | *.scc
69 |
70 | # Chutzpah Test files
71 | _Chutzpah*
72 |
73 | # Visual C++ cache files
74 | ipch/
75 | *.aps
76 | *.ncb
77 | *.opensdf
78 | *.sdf
79 | *.cachefile
80 |
81 | # Visual Studio profiler
82 | *.psess
83 | *.vsp
84 | *.vspx
85 |
86 | # TFS 2012 Local Workspace
87 | $tf/
88 |
89 | # Guidance Automation Toolkit
90 | *.gpState
91 |
92 | # ReSharper is a .NET coding add-in
93 | _ReSharper*/
94 | *.[Rr]e[Ss]harper
95 | *.DotSettings.user
96 |
97 | # JustCode is a .NET coding add-in
98 | .JustCode
99 |
100 | # TeamCity is a build add-in
101 | _TeamCity*
102 |
103 | # DotCover is a Code Coverage Tool
104 | *.dotCover
105 |
106 | # NCrunch
107 | _NCrunch_*
108 | .*crunch*.local.xml
109 |
110 | # MightyMoose
111 | *.mm.*
112 | AutoTest.Net/
113 |
114 | # Web workbench (sass)
115 | .sass-cache/
116 |
117 | # Installshield output folder
118 | [Ee]xpress/
119 |
120 | # DocProject is a documentation generator add-in
121 | DocProject/buildhelp/
122 | DocProject/Help/*.HxT
123 | DocProject/Help/*.HxC
124 | DocProject/Help/*.hhc
125 | DocProject/Help/*.hhk
126 | DocProject/Help/*.hhp
127 | DocProject/Help/Html2
128 | DocProject/Help/html
129 |
130 | # Click-Once directory
131 | publish/
132 |
133 | # Publish Web Output
134 | *.[Pp]ublish.xml
135 | *.azurePubxml
136 | # TODO: Comment the next line if you want to checkin your web deploy settings
137 | # but database connection strings (with potential passwords) will be unencrypted
138 | *.pubxml
139 | *.publishproj
140 |
141 | # NuGet Packages
142 | *.nupkg
143 | # The packages folder can be ignored because of Package Restore
144 | **/packages/*
145 | # except build/, which is used as an MSBuild target.
146 | !**/packages/build/
147 | # Uncomment if necessary however generally it will be regenerated when needed
148 | #!**/packages/repositories.config
149 |
150 | # Windows Azure Build Output
151 | csx/
152 | *.build.csdef
153 |
154 | # Windows Store app package directory
155 | AppPackages/
156 |
157 | # Visual Studio cache files
158 | # files ending in .cache can be ignored
159 | *.[Cc]ache
160 | # but keep track of directories ending in .cache
161 | !*.[Cc]ache/
162 |
163 | # Others
164 | ClientBin/
165 | [Ss]tyle[Cc]op.*
166 | ~$*
167 | *~
168 | *.dbmdl
169 | *.dbproj.schemaview
170 | *.pfx
171 | *.publishsettings
172 | node_modules/
173 | bower_components/
174 | orleans.codegen.cs
175 |
176 | # RIA/Silverlight projects
177 | Generated_Code/
178 |
179 | # Backup & report files from converting an old project file
180 | # to a newer Visual Studio version. Backup files are not needed,
181 | # because we have git ;-)
182 | _UpgradeReport_Files/
183 | Backup*/
184 | UpgradeLog*.XML
185 | UpgradeLog*.htm
186 |
187 | # SQL Server files
188 | *.mdf
189 | *.ldf
190 |
191 | # Business Intelligence projects
192 | *.rdl.data
193 | *.bim.layout
194 | *.bim_*.settings
195 |
196 | # Microsoft Fakes
197 | FakesAssemblies/
198 |
199 | # Node.js Tools for Visual Studio
200 | .ntvs_analysis.dat
201 |
202 | # Visual Studio 6 build log
203 | *.plg
204 |
205 | # Visual Studio 6 workspace options file
206 | *.opt
207 |
208 | !x64/Release/siappdll.dll
209 | !x64/Release/
210 | !x64/
211 |
--------------------------------------------------------------------------------
/AddIns/spconvd/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #define DEBUG
13 | #ifdef DEBUG
14 | #define DPRN(format, args...) printf(format, ##args)
15 | #else
16 | #define DPRN(format, args...) do {} while (0)
17 | #endif
18 |
19 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
20 |
21 | #define SOCK_FILE "/var/run/spnav.sock"
22 | #define PORT 11111
23 |
24 | // decreasing events rate from spacemouse - this need for decrease rate of screen refresh in fusion360 - decrease cpu load
25 | #define SHAPE
26 | #define SHAPE_DELAY_MS 30
27 | #define SHAPE_DELAY_US (SHAPE_DELAY_MS * 1000)
28 |
29 | #ifdef SHAPE
30 | #define POLL_TIMEOUT SHAPE_DELAY_MS
31 | #else
32 | #define POLL_TIMEOUT -1
33 | #endif
34 |
35 | #ifdef SHAPE
36 | unsigned int get_time_us(void)
37 | {
38 | struct timespec tp;
39 | clock_gettime(CLOCK_MONOTONIC_RAW, &tp);
40 | return tp.tv_sec * 1000000 + tp.tv_nsec / 1000;
41 | }
42 | #endif
43 |
44 | int daem_connect(void)
45 | {
46 | int daemfd = socket(AF_UNIX, SOCK_STREAM, 0);
47 | if (daemfd < 0) {
48 | DPRN("could not create unix sock\n");
49 | return -1;
50 | }
51 |
52 | struct sockaddr_un addr_un = {0};
53 |
54 | addr_un.sun_family = AF_UNIX;
55 | strncpy(addr_un.sun_path, SOCK_FILE, sizeof(addr_un.sun_path) - 1);
56 |
57 | if (connect(daemfd, (struct sockaddr*)&addr_un, sizeof(addr_un))) {
58 | DPRN("could not connect to spacenavd\n");
59 | close(daemfd);
60 | return -1;
61 | }
62 |
63 | return daemfd;
64 | }
65 |
66 | void daem_close(int fd)
67 | {
68 | close(fd);
69 | }
70 |
71 | int main(void)
72 | {
73 | if (daemon(0, 1)) {
74 | DPRN("could not daemonize\n");
75 | return -1;
76 | }
77 |
78 | int listenfd = socket(AF_INET, SOCK_STREAM, 0);
79 | if (listenfd < 0) {
80 | DPRN("could not create inet sock\n");
81 | return -1;
82 | }
83 |
84 | int enable = 1;
85 | setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
86 |
87 | struct sockaddr_in addr_in = {0};
88 | addr_in.sin_family = AF_INET;
89 | addr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
90 | addr_in.sin_port = htons(PORT);
91 |
92 | if (bind(listenfd, (struct sockaddr*)&addr_in, sizeof(addr_in))) {
93 | DPRN("could bind\n");
94 | close(listenfd);
95 | return -1;
96 | }
97 |
98 | listen(listenfd, 1);
99 |
100 | while (1) {
101 | DPRN("waiting for connection\n");
102 |
103 | int confd = accept(listenfd, (struct sockaddr*)NULL, NULL);
104 | if (confd < 0) {
105 | printf("could not accept\n");
106 | continue;
107 | }
108 |
109 | DPRN("connection accepted\n");
110 |
111 | int daemfd = daem_connect();
112 | if (daemfd >= 0)
113 | DPRN("daemon connection success\n");
114 | else
115 | continue;
116 |
117 | struct pollfd fds[2];
118 |
119 | fds[0].fd = confd;
120 | fds[0].events = POLLIN;
121 |
122 | fds[1].fd = daemfd;
123 | fds[1].events = POLLIN;
124 |
125 | int motion[8] = {0};
126 |
127 | #ifdef SHAPE
128 | unsigned int last = get_time_us();
129 | #endif
130 | int run = 1;
131 | while (run) {
132 | int i;
133 | int ret = poll(fds, ARRAY_SIZE(fds), POLL_TIMEOUT);
134 |
135 | #ifdef SHAPE
136 | unsigned int now = get_time_us();
137 |
138 | if ((now - last) > SHAPE_DELAY_US) {
139 | int sum = 0;
140 | for (i = 1; i < 7; i++)
141 | sum |= motion[i];
142 | if (sum) {
143 | if (write(confd, motion, sizeof(motion)) != sizeof(motion)) {
144 | run = 0;
145 | break;
146 | }
147 | bzero(motion, sizeof(motion));
148 | }
149 |
150 | last = now;
151 | }
152 | #endif
153 |
154 | if (ret <= 0) {
155 | if (ret < 0)
156 | DPRN("poll() failed\n");
157 | continue;
158 | }
159 |
160 | for (i = 0; i < ARRAY_SIZE(fds); i++) {
161 | if(fds[i].revents == 0)
162 | continue;
163 |
164 | if(fds[i].revents != POLLIN) {
165 | DPRN("poll() invalid revents == 0x%04x fds[%d]\n", fds[i].revents, i);
166 | continue;
167 | }
168 |
169 | if (fds[i].fd == confd) {
170 | run = 0;
171 | break;
172 | }
173 |
174 | if (fds[i].fd == daemfd) {
175 | int data[8];
176 | ssize_t len = read(daemfd, data, sizeof(data));
177 | if (len <= 0) {
178 | run = 0;
179 | break;
180 | }
181 | #ifdef SHAPE
182 | if (data[0] == 0) {
183 | int j;
184 | for (j = 1; j < 7; j++)
185 | motion[j] += data[j];
186 | }
187 | else
188 | #endif
189 | {
190 | if (write(confd, data, len) != len) {
191 | run = 0;
192 | break;
193 | }
194 | }
195 | }
196 | }
197 | }
198 |
199 | DPRN("daemon connection close\n");
200 | daem_close(daemfd);
201 |
202 | DPRN("close connection\n");
203 | close(confd);
204 | }
205 |
206 | close(listenfd);
207 |
208 | return 0;
209 | }
210 |
--------------------------------------------------------------------------------
/siappdll/siappdll.vcproj:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
26 |
29 |
32 |
35 |
38 |
41 |
54 |
57 |
60 |
63 |
72 |
75 |
78 |
81 |
84 |
87 |
90 |
93 |
94 |
102 |
105 |
108 |
111 |
114 |
117 |
129 |
132 |
135 |
138 |
149 |
152 |
155 |
158 |
161 |
164 |
167 |
170 |
171 |
172 |
173 |
174 |
175 |
180 |
183 |
184 |
187 |
188 |
191 |
192 |
195 |
196 |
197 |
202 |
205 |
206 |
209 |
210 |
213 |
214 |
217 |
218 |
221 |
222 |
223 |
228 |
229 |
230 |
231 |
232 |
233 |
--------------------------------------------------------------------------------
/AddIns/SpaceMouse/SpaceMouse.py:
--------------------------------------------------------------------------------
1 | #Author-
2 | #Description-
3 |
4 | import adsk.core, adsk.fusion, adsk.cam, traceback
5 | import threading, random, json, socket, array, math
6 |
7 | HOST = "127.0.0.1"
8 | PORT = 11111
9 |
10 | app = None
11 | ui = None
12 | handlers = []
13 | stopFlag = None
14 | myCustomEvent = 'MyCustomEventId'
15 | customEvent = None
16 |
17 | mysock = None
18 |
19 | check = False
20 |
21 | def sign(x):
22 | return 1 if x > 0 else -1 if x < 0 else 0
23 |
24 | # The event handler that responds to the custom event being fired.
25 | class ThreadEventHandler(adsk.core.CustomEventHandler):
26 | def __init__(self):
27 | super().__init__()
28 | def notify(self, args):
29 | try:
30 | global app
31 |
32 | rotx_en = roty_en = rotz_en = movx_en = movy_en = movz_en = False
33 |
34 | rotx_en = True
35 | roty_en = True
36 | rotz_en = True
37 | movx_en = True
38 | movy_en = True
39 | movz_en = True
40 |
41 | eventArgs = json.loads(args.additionalInfo)
42 |
43 | rx = eventArgs['rx']
44 | ry = eventArgs['ry']
45 | rz = eventArgs['rz']
46 | x = eventArgs['x']
47 | y = eventArgs['y']
48 | z = eventArgs['z']
49 |
50 | # get state
51 | vi = app.activeViewport
52 | camera = vi.camera #This is a deep copy.
53 | eye = camera.eye
54 | tgt = camera.target
55 | up = camera.upVector
56 |
57 | # calc coef
58 | coef = math.sqrt(camera.viewExtents)
59 |
60 | MOV_COEF = 0.0002 * coef
61 | ROT_COEF = 0.00015
62 | TILT_COEF = 0.00007
63 | ZOOM_COEF = 0.0005 * coef
64 |
65 |
66 | # get matrix
67 | front = eye.vectorTo(tgt)
68 | right = front.crossProduct(up)
69 |
70 | matr = adsk.core.Matrix3D.create()
71 | matr.setWithCoordinateSystem(eye, right, front, up)
72 |
73 | if rotx_en:
74 | rotx = adsk.core.Matrix3D.create()
75 | rotx.setToRotation(-rx * TILT_COEF, right, tgt)
76 |
77 | matr.transformBy(rotx)
78 |
79 | if rotz_en:
80 | rotz = adsk.core.Matrix3D.create()
81 | rotz.setToRotation(-ry * ROT_COEF, up, tgt)
82 |
83 | matr.transformBy(rotz)
84 |
85 | if roty_en:
86 | roty = adsk.core.Matrix3D.create()
87 | roty.setToRotation(-rz * TILT_COEF, front, tgt)
88 |
89 | matr.transformBy(roty)
90 |
91 | (eye, right, front, up) = matr.getAsCoordinateSystem()
92 |
93 | if movx_en:
94 | movx = right.copy()
95 | movx.normalize()
96 | movx.scaleBy(-x * MOV_COEF)
97 |
98 | eye.translateBy(movx)
99 | tgt.translateBy(movx)
100 |
101 | if movy_en:
102 | movy = up.copy()
103 | movy.normalize()
104 | movy.scaleBy(-y * MOV_COEF)
105 |
106 | eye.translateBy(movy)
107 | tgt.translateBy(movy)
108 |
109 | if movz_en:
110 | ve = camera.viewExtents
111 | ve += z * ZOOM_COEF
112 | if ve > 0:
113 | camera.viewExtents = ve
114 |
115 |
116 | # write back
117 | camera.isSmoothTransition = False
118 |
119 | camera.target = tgt
120 | camera.eye = eye
121 | camera.upVector = up
122 | vi.camera = camera
123 | vi.refresh()
124 |
125 | #adsk.doEvents()
126 | except:
127 | if ui:
128 | ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
129 |
130 |
131 | # The class for the new thread.
132 | class MyThread(threading.Thread):
133 | def __init__(self, event):
134 | threading.Thread.__init__(self)
135 | self.stopped = event
136 |
137 | def run(self):
138 | global mysock
139 |
140 | mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
141 | mysock.connect((HOST, PORT))
142 |
143 | while True:
144 | data = mysock.recv(32)
145 | arr = array.array('i', data)
146 | if arr[0] == 0:
147 | args = {'x': arr[1], 'y': arr[2], 'z': arr[3], 'rx': arr[4], 'ry': arr[5], 'rz': arr[6]}
148 | app.fireCustomEvent(myCustomEvent, json.dumps(args))
149 |
150 | def run(context):
151 | global ui
152 | global app
153 |
154 | try:
155 | app = adsk.core.Application.get()
156 | ui = app.userInterface
157 |
158 | ui.messageBox('SpaceMouse start !!!')
159 |
160 | # Register the custom event and connect the handler.
161 | global customEvent
162 | customEvent = app.registerCustomEvent(myCustomEvent)
163 |
164 | onThreadEvent = ThreadEventHandler()
165 | customEvent.add(onThreadEvent)
166 | handlers.append(onThreadEvent)
167 |
168 | # Create a new thread for the other processing.
169 | global stopFlag
170 | stopFlag = threading.Event()
171 | myThread = MyThread(stopFlag)
172 | myThread.start()
173 | except:
174 | if ui:
175 | ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
176 |
177 |
178 | def stop(context):
179 | global mysock
180 | try:
181 | mysock.close()
182 |
183 | if handlers.count:
184 | customEvent.remove(handlers[0])
185 |
186 | stopFlag.set()
187 | app.unregisterCustomEvent(myCustomEvent)
188 | ui.messageBox('Stop addin')
189 | except:
190 | if ui:
191 | ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
192 |
--------------------------------------------------------------------------------
/siappdll/src/syncapi.h:
--------------------------------------------------------------------------------
1 | /*
2 | SpaceNavigatorEmulator - 3dconnexion-compatible siappdll.dll replacement
3 | Copyright (C) 2014 John Tsiombikas
4 | Copyright (C) 2015 Luke Nuttall
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | #pragma once
21 | #include "sidef.h"
22 |
23 | extern "C" {
24 |
25 | typedef struct SiSyncAxesState {
26 | int state;
27 | } SiSyncAxesState;
28 |
29 | typedef enum SiSyncAbsFunctionNumber {
30 | SI_SYNC_FUNCTION_MENU_TOGGLE = 12,
31 | SI_SYNC_FUNCTION_TRANS_TOGGLE = 13,
32 | SI_SYNC_FUNCTION_ROT_TOGGLE = 14,
33 | SI_SYNC_FUNCTION_HPV_TOGGLE = 15,
34 | SI_SYNC_FUNCTION_DEC_SENS = 16,
35 | SI_SYNC_FUNCTION_INC_SENS = 17,
36 | SI_SYNC_FUNCTION_RESTORE_DEF = 18,
37 | SI_SYNC_FUNCTION_PAN = 19,
38 | SI_SYNC_FUNCTION_ZOOM = 20,
39 | SI_SYNC_FUNCTION_TX = 21,
40 | SI_SYNC_FUNCTION_TY = 22,
41 | SI_SYNC_FUNCTION_TZ = 23,
42 | SI_SYNC_FUNCTION_RX = 24,
43 | SI_SYNC_FUNCTION_RY = 25,
44 | SI_SYNC_FUNCTION_RZ = 26,
45 | SI_SYNC_FUNCTION_REZERO_DEVICE = 27,
46 | SI_SYNC_FUNCTION_SAVE = 33,
47 | SI_SYNC_FUNCTION_RELOAD = 57,
48 | SI_SYNC_FUNCTION_SHIFT_KEY = 60,
49 | SI_SYNC_FUNCTION_CTRL_KEY = 61,
50 | SI_SYNC_FUNCTION_ALT_KEY = 62,
51 | SI_SYNC_FUNCTION_RESTORE_SENS = 63,
52 | SI_SYNC_FUNCTION_SPACE_KEY = 64,
53 | SI_SYNC_FUNCTION_CTRL_SHIFT_KEY = 65,
54 | SI_SYNC_FUNCTION_CTRL_ALT_KEY = 66,
55 | SI_SYNC_FUNCTION_SHIFT_ALT_KEY = 67,
56 | SI_SYNC_FUNCTION_TAB_KEY = 68,
57 | SI_SYNC_FUNCTION_RETURN_KEY = 69,
58 | SI_SYNC_FUNCTION_DEC_TRANS_SENS = 70,
59 | SI_SYNC_FUNCTION_INC_TRANS_SENS = 71,
60 | SI_SYNC_FUNCTION_DEC_ROT_SENS = 72,
61 | SI_SYNC_FUNCTION_INC_ROT_SENS = 73,
62 | SI_SYNC_FUNCTION_DEC_PAN_SENS = 74,
63 | SI_SYNC_FUNCTION_INC_PAN_SENS = 75,
64 | SI_SYNC_FUNCTION_DEC_ZOOM_SENS = 76,
65 | SI_SYNC_FUNCTION_INC_ZOOM_SENS = 77,
66 | SI_SYNC_FUNCTION_ESC_KEY = 78,
67 | SI_SYNC_FUNCTION_3DX_HELP = 94,
68 | SI_SYNC_FUNCTION_APP_HELP = 95,
69 | SI_SYNC_FUNCTION_DIALOG_TOGGLE_FN = 96,
70 | SI_SYNC_FUNCTION_FIT_FN = 97,
71 | SI_SYNC_FUNCTION_TOGGLE_3DXLCD_FN = 198,
72 | SI_SYNC_FUNCTION_TOGGLE_3DXNUMPAD_FN = 199
73 | } SiSyncAbsFunctionNumber;
74 |
75 |
76 | typedef enum SiSyncFilter {
77 | SI_SYNC_FILTER_TRANSLATIONS = 1,
78 | SI_SYNC_FILTER_ROTATIONS = 2,
79 | SI_SYNC_FILTER_DOMINANT = 3
80 | } SiSyncFilter;
81 |
82 | typedef enum SiSyncFilterValue {
83 | SI_SYNC_FILTER_OFF = 0,
84 | SI_SYNC_FILTER_ON = 1,
85 | SI_SYNC_FILTER_IN_BETWEEN = 2
86 | } SiSyncFilterValue;
87 |
88 | typedef enum SiSyncAxesStateBits {
89 | SI_SYNC_AXES_STATE_TX = (1 << 0),
90 | SI_SYNC_AXES_STATE_TY = (1 << 1),
91 | SI_SYNC_AXES_STATE_TZ = (1 << 2),
92 | SI_SYNC_AXES_STATE_RX = (1 << 3),
93 | SI_SYNC_AXES_STATE_RY = (1 << 4),
94 | SI_SYNC_AXES_STATE_RZ = (1 << 5)
95 | } SiSyncAxesStateBits;
96 |
97 | typedef enum SiSyncButtonState {
98 | SI_SYNC_BUTTON_STATE_OFF = 0,
99 | SI_SYNC_BUTTON_STATE_ON = 1,
100 | SI_SYNC_BUTTON_STATE_DISABLED = 2
101 | } SiSyncButtonState;
102 |
103 | SpwRetVal SPWAPI SiSyncSendQuery(struct SiHdl *si);
104 | SpwRetVal SPWAPI SiSyncGetVersion(struct SiHdl *si, SPWuint32 *major, SPWuint32 *minor);
105 | SpwRetVal SPWAPI SiSyncGetNumberOfFunctions(struct SiHdl *si, SPWuint32 *num_func);
106 | SpwRetVal SPWAPI SiSyncGetFunction(struct SiHdl *hdl, SPWuint32 index, SPWint32 *abs_func_num, wchar_t *name, SPWuint32 *name_len);
107 | SpwRetVal SPWAPI SiSyncGetButtonAssignment(struct SiHdl *hdl, SPWuint32 bn_num, SPWint32 *assigned_func_index);
108 | SpwRetVal SPWAPI SiSyncSetButtonAssignment(struct SiHdl *hdl, SPWuint32 bn_num, SPWint32 func_index);
109 | SpwRetVal SPWAPI SiSyncSetButtonAssignmentAbsolute(struct SiHdl *hdl, SPWuint32 bn_num, SPWint32 abs_func_num);
110 | SpwRetVal SPWAPI SiSyncSetButtonName(struct SiHdl *hdl, SPWuint32 bn_num, const wchar_t *name);
111 | SpwRetVal SPWAPI SiSyncGetAxisLabel(struct SiHdl *hdl, SPWuint32 axis_num, wchar_t *name, SPWuint32 *name_len);
112 | SpwRetVal SPWAPI SiSyncSetAxisLabel(struct SiHdl *hdl, SPWuint32 axis_num, const wchar_t *name);
113 | SpwRetVal SPWAPI SiSyncGetOrientation(struct SiHdl *hdl, SPWint32 axes[6]);
114 | SpwRetVal SPWAPI SiSyncSetOrientation(struct SiHdl *hdl, const SPWint32 axes[6]);
115 | SpwRetVal SPWAPI SiSyncGetFilter(struct SiHdl *hdl, SiSyncFilter i, SiSyncFilterValue *pv);
116 | SpwRetVal SPWAPI SiSyncSetFilter(struct SiHdl *hdl, SiSyncFilter i, SiSyncFilterValue v);
117 | SpwRetVal SPWAPI SiSyncGetAxesState(struct SiHdl *hdl, SiSyncAxesState *pa);
118 | SpwRetVal SPWAPI SiSyncSetAxesState(struct SiHdl *hdl, SiSyncAxesState a);
119 | SpwRetVal SPWAPI SiSyncSetInfoLine(struct SiHdl *hdl, SPWint32 duration, const wchar_t *text);
120 | SpwRetVal SPWAPI SiSyncGetScaleOverall(struct SiHdl *hdl, SPWfloat32 *pv);
121 | SpwRetVal SPWAPI SiSyncSetScaleOverall(struct SiHdl *hdl, SPWfloat32 v);
122 | SpwRetVal SPWAPI SiSyncGetScaleTx(struct SiHdl *hdl, SPWfloat32 *pv);
123 | SpwRetVal SPWAPI SiSyncSetScaleTx(struct SiHdl *hdl, SPWfloat32 v);
124 | SpwRetVal SPWAPI SiSyncGetScaleTy(struct SiHdl *hdl, SPWfloat32 *pv);
125 | SpwRetVal SPWAPI SiSyncSetScaleTy(struct SiHdl *hdl, SPWfloat32 v);
126 | SpwRetVal SPWAPI SiSyncGetScaleTz(struct SiHdl *hdl, SPWfloat32 *pv);
127 | SpwRetVal SPWAPI SiSyncSetScaleTz(struct SiHdl *hdl, SPWfloat32 v);
128 | SpwRetVal SPWAPI SiSyncGetScaleRx(struct SiHdl *hdl, SPWfloat32 *pv);
129 | SpwRetVal SPWAPI SiSyncSetScaleRx(struct SiHdl *hdl, SPWfloat32 v);
130 | SpwRetVal SPWAPI SiSyncGetScaleRy(struct SiHdl *hdl, SPWfloat32 *pv);
131 | SpwRetVal SPWAPI SiSyncSetScaleRy(struct SiHdl *hdl, SPWfloat32 v);
132 | SpwRetVal SPWAPI SiSyncGetScaleRz(struct SiHdl *hdl, SPWfloat32 *pv);
133 | SpwRetVal SPWAPI SiSyncSetScaleRz(struct SiHdl *hdl, SPWfloat32 v);
134 | SpwRetVal SPWAPI SiSyncInvokeAbsoluteFunction(struct SiHdl *hdl, SiSyncAbsFunctionNumber i);
135 | SpwRetVal SPWAPI SiSyncSetButtonState(struct SiHdl *hdl, SPWuint32 bn_num, SiSyncButtonState state);
136 |
137 | }
--------------------------------------------------------------------------------
/siappdll/src/sidef.h:
--------------------------------------------------------------------------------
1 | /*
2 | SpaceNavigatorEmulator - 3dconnexion-compatible siappdll.dll replacement
3 | Copyright (C) 2014 John Tsiombikas
4 | Copyright (C) 2015 Luke Nuttall
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 | #pragma once
20 |
21 | #define SPWAPI WINAPI
22 |
23 | #include
24 |
25 | #ifndef _MSC_VER
26 | #include
27 | #else
28 | typedef __int32 int32_t;
29 | typedef unsigned __int32 uint32_t;
30 | #endif
31 |
32 | typedef int32_t SPWint32;
33 | typedef uint32_t SPWuint32;
34 | typedef long SPWbool;
35 | typedef float SPWfloat32;
36 | typedef double SPWfloat64;
37 |
38 | #define SI_RESET_BUTTON 0
39 | #define SI_PICK_BUTTON 31
40 | #define SI_DIALOG_BUTTON 30
41 |
42 | #define SI_RESET_BIT (1L << SI_RESET_BUTTON)
43 | #define SI_PICK_BIT (1L << SI_PICK_BUTTON)
44 | #define SI_DIALOG_BIT (1L << SI_DIALOG_BUTTON)
45 |
46 | #define SI_STRSIZE 128
47 | #define SI_MAXBUF 128
48 | #define SI_MAXPORTNAME 128
49 |
50 | #define SI_NO_MASK 0
51 |
52 | struct SiHdl;
53 |
54 | #pragma pack(push, 4)
55 |
56 | typedef int SiDevID;
57 |
58 | typedef struct SiButtonData {
59 | unsigned long last; /* previous button bitmask */
60 | unsigned long current; /* current button bitmask */
61 | unsigned long pressed; /* buttons pressed */
62 | unsigned long release; /* buttons released */
63 | } SiButtonData;
64 |
65 | typedef struct SiDevInfo {
66 | int dev_type;
67 | int num_buttons;
68 | int num_degrees;
69 | SPWbool can_beep;
70 | char firmware[SI_STRSIZE];
71 | } SiDevInfo;
72 |
73 | typedef struct SiGetEventData {
74 | unsigned int msg;
75 | unsigned int wparam;
76 | long lparam;
77 | } SiGetEventData;
78 |
79 | typedef struct SiOpenData {
80 | void *win;
81 | void *trans_ctl;
82 | unsigned long pid;
83 | char exe_file[MAX_PATH];
84 | int lib_flag;
85 | } SiOpenData;
86 |
87 | typedef struct SiTypeMask {
88 | unsigned char mask[8];
89 | } SiTypeMask;
90 |
91 | /* SiSpwData::motion[6] index names */
92 | enum { SI_TX, SI_TY, SI_TZ, SI_RX, SI_RY, SI_RZ };
93 |
94 | typedef struct SiSpwData {
95 | SiButtonData button;
96 | long motion[6];
97 | unsigned long period;
98 | } SiSpwData;
99 |
100 | typedef enum SiEventType {
101 | SI_BUTTON_EVENT = 1,
102 | SI_MOTION_EVENT,
103 | SI_COMBO_EVENT,
104 | SI_ZERO_EVENT,
105 | SI_EXCEPTION_EVENT,
106 | SI_OUT_OF_BAND,
107 | SI_ORIENTATION_EVENT,
108 | SI_KEYBOARD_EVENT,
109 | SI_LPFK_EVENT,
110 | SI_APP_EVENT,
111 | SI_SYNC_EVENT,
112 | SI_BUTTON_PRESS_EVENT,
113 | SI_BUTTON_RELEASE_EVENT,
114 | SI_DEVICE_CHANGE_EVENT,
115 | SI_MOUSE_EVENT,
116 | SI_JOYSTICK_EVENT
117 | } SiEventType;
118 |
119 | typedef enum SiOrientation { SI_LEFT, SI_RIGHT } SiOrientation;
120 |
121 | typedef struct /* Data for SI_BUTTON_PRESS/RELEASE_EVENT */
122 | {
123 | SPWuint32 buttonNumber; /* The button number that went down/up in a *
124 | * SI_BUTTON_PRESS/RELEASE_EVENT event */
125 | } SiHWButtonData;
126 |
127 | typedef struct SiSpwEvent {
128 | int type;
129 | union {
130 | SiSpwData spw_data;
131 | SiOrientation spw_orient;
132 | char ex_data[SI_MAXBUF]; /* exception data */
133 | SiHWButtonData hwButtonEvent;
134 | } u;
135 | } SiSpwEvent;
136 |
137 | typedef struct {
138 | int (*func)(SiOpenData*, SiGetEventData*, SiSpwEvent*, void*);
139 | void *cls;
140 | } SiEventHandler;
141 |
142 | typedef struct SiSpwHandlers {
143 | SiEventHandler button, motion, combo, zero, exception;
144 | } SiSpwHandlers;
145 |
146 | typedef struct SiVerInfo {
147 | int major, minor, build;
148 | char version[SI_STRSIZE];
149 | char data[SI_STRSIZE];
150 | } SiVerInfo;
151 |
152 | typedef struct SiDevPort {
153 | SiDevID devID; /* Device ID */
154 | int devType; /* Device type */
155 | int devClass; /* Device class */
156 | char devName[SI_STRSIZE]; /* Device name */
157 | char portName[SI_MAXPORTNAME];
158 | } SiDevPort;
159 |
160 | typedef struct SiDeviceName {
161 | char name[SI_STRSIZE];
162 | } SiDeviceName;
163 |
164 | typedef struct SiButtonName {
165 | char name[SI_STRSIZE];
166 | } SiButtonName;
167 |
168 | typedef struct SiPortName {
169 | char name[SI_STRSIZE];
170 | } SiPortName;
171 |
172 | typedef enum SiDevTypes {
173 | SI_ALL_TYPES = -1,
174 | SI_UNKNOWN_DEVICE = 0,
175 | SI_SPACEBALL_2003 = 1,
176 | SI_SPACEBALL_3003 = 2,
177 | SI_SPACE_CONTROLLER = 3,
178 | SI_SPACEEXPLORER = 4,
179 | SI_SPACENAVIGATOR_FOR_NOTEBOOKS = 5,
180 | SI_SPACENAVIGATOR = 6,
181 | SI_SPACEBALL_2003A = 7,
182 | SI_SPACEBALL_2003B = 8,
183 | SI_SPACEBALL_2003C = 9,
184 | SI_SPACEBALL_3003A = 10,
185 | SI_SPACEBALL_3003B = 11,
186 | SI_SPACEBALL_3003C = 12,
187 | SI_SPACEBALL_4000 = 13,
188 | SI_SPACEMOUSE_CLASSIC = 14,
189 | SI_SPACEMOUSE_PLUS = 15,
190 | SI_SPACEMOUSE_XT = 16,
191 | SI_CYBERMAN = 17,
192 | SI_CADMAN = 18,
193 | SI_SPACEMOUSE_CLASSIC_PROMO = 19,
194 | SI_SERIAL_CADMAN = 20,
195 | SI_SPACEBALL_5000 = 21,
196 | SI_TEST_NO_DEVICE = 22,
197 | SI_3DX_KEYBOARD_BLACK = 23,
198 | SI_3DX_KEYBOARD_WHITE = 24,
199 | SI_TRAVELER = 25,
200 | SI_TRAVELER1 = 26,
201 | SI_SPACEBALL_5000A = 27,
202 | SI_SPACEDRAGON = 28,
203 | SI_SPACEPILOT = 29,
204 | SI_MB = 30,
205 | SI_SPACEPILOT_PRO = 0xc629,
206 | SI_SPACEMOUSE_PRO = 0xc62b
207 | } SiDevType;
208 |
209 |
210 |
211 | enum SpwRetVal {
212 | SPW_NO_ERROR , /* no error */
213 | SPW_ERROR, /* error -- function failed */
214 | SI_BAD_HANDLE, /* invalid 3DxWare handle */
215 | SI_BAD_ID, /* invalid device ID */
216 | SI_BAD_VALUE, /* invalid argument value */
217 | SI_IS_EVENT, /* event is a 3DxWare event */
218 | SI_SKIP_EVENT, /* skip this 3DxWare event */
219 | SI_NOT_EVENT, /* event is not a 3DxWare event */
220 | SI_NO_DRIVER, /* 3DxWare driver is not running */
221 | SI_NO_RESPONSE, /* 3DxWare driver is not responding */
222 | SI_UNSUPPORTED, /* the function is unsupported by this version */
223 | SI_UNINITIALIZED, /* 3DxWare Input Library is uninitialized */
224 | SI_WRONG_DRIVER, /* incorrect driver for this 3DxWare version */
225 | SI_INTERNAL_ERROR /* internal 3DxWare error */
226 | };
227 |
228 | #pragma pack(pop) /* restore default packing */
229 |
--------------------------------------------------------------------------------
/siappdll/src/syncapi.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | SpaceNavigatorEmulator - 3dconnexion-compatible siappdll.dll replacement
3 | Copyright (C) 2014 John Tsiombikas
4 | Copyright (C) 2015 Luke Nuttall
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 | #include
20 | #include "syncapi.h"
21 | #include "log.h"
22 |
23 | SpwRetVal SPWAPI SiSyncSendQuery(struct SiHdl *si)
24 | {
25 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
26 | return SPW_NO_ERROR;
27 | }
28 |
29 | enum SpwRetVal SPWAPI SiSyncGetVersion(struct SiHdl *si, SPWuint32 *major, SPWuint32 *minor)
30 | {
31 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
32 | return SPW_NO_ERROR;
33 | }
34 |
35 | enum SpwRetVal SPWAPI SiSyncGetNumberOfFunctions(struct SiHdl *si, SPWuint32 *num_func)
36 | {
37 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
38 | return SPW_NO_ERROR;
39 | }
40 |
41 | enum SpwRetVal SPWAPI SiSyncGetFunction(struct SiHdl *hdl, SPWuint32 index, SPWint32 *abs_func_num, wchar_t *name, SPWuint32 *name_len)
42 | {
43 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
44 | return SPW_NO_ERROR;
45 | }
46 |
47 | enum SpwRetVal SPWAPI SiSyncGetButtonAssignment(struct SiHdl *hdl, SPWuint32 bn_num, SPWint32 *assigned_func_index)
48 | {
49 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
50 | return SPW_NO_ERROR;
51 | }
52 |
53 | enum SpwRetVal SPWAPI SiSyncSetButtonAssignment(struct SiHdl *hdl, SPWuint32 bn_num, SPWint32 func_index)
54 | {
55 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
56 | return SPW_NO_ERROR;
57 | }
58 |
59 | enum SpwRetVal SPWAPI SiSyncSetButtonAssignmentAbsolute(struct SiHdl *hdl, SPWuint32 bn_num, SPWint32 abs_func_num)
60 | {
61 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
62 | return SPW_NO_ERROR;
63 | }
64 |
65 | enum SpwRetVal SPWAPI SiSyncSetButtonName(struct SiHdl *hdl, SPWuint32 bn_num, const wchar_t *name)
66 | {
67 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
68 | return SPW_NO_ERROR;
69 | }
70 |
71 | enum SpwRetVal SPWAPI SiSyncGetAxisLabel(struct SiHdl *hdl, SPWuint32 axis_num, wchar_t *name, SPWuint32 *name_len)
72 | {
73 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
74 | return SPW_NO_ERROR;
75 | }
76 |
77 | enum SpwRetVal SPWAPI SiSyncSetAxisLabel(struct SiHdl *hdl, SPWuint32 axis_num, const wchar_t *name)
78 | {
79 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
80 | return SPW_NO_ERROR;
81 | }
82 |
83 | enum SpwRetVal SPWAPI SiSyncGetOrientation(struct SiHdl *hdl, SPWint32 axes[6])
84 | {
85 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
86 | return SPW_NO_ERROR;
87 | }
88 |
89 | enum SpwRetVal SPWAPI SiSyncSetOrientation(struct SiHdl *hdl, const SPWint32 axes[6])
90 | {
91 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
92 | return SPW_NO_ERROR;
93 | }
94 |
95 | enum SpwRetVal SPWAPI SiSyncGetFilter(struct SiHdl *hdl, SiSyncFilter i, SiSyncFilterValue *pv)
96 | {
97 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
98 | return SPW_NO_ERROR;
99 | }
100 |
101 | enum SpwRetVal SPWAPI SiSyncSetFilter(struct SiHdl *hdl, SiSyncFilter i, SiSyncFilterValue v)
102 | {
103 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
104 | return SPW_NO_ERROR;
105 | }
106 |
107 | enum SpwRetVal SPWAPI SiSyncGetAxesState(struct SiHdl *hdl, SiSyncAxesState *pa)
108 | {
109 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
110 | return SPW_NO_ERROR;
111 | }
112 |
113 | enum SpwRetVal SPWAPI SiSyncSetAxesState(struct SiHdl *hdl, SiSyncAxesState a)
114 | {
115 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
116 | return SPW_NO_ERROR;
117 | }
118 |
119 | enum SpwRetVal SPWAPI SiSyncSetInfoLine(struct SiHdl *hdl, SPWint32 duration, const wchar_t *text)
120 | {
121 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
122 | return SPW_NO_ERROR;
123 | }
124 |
125 | enum SpwRetVal SPWAPI SiSyncGetScaleOverall(struct SiHdl *hdl, SPWfloat32 *pv)
126 | {
127 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
128 | return SPW_NO_ERROR;
129 | }
130 |
131 | enum SpwRetVal SPWAPI SiSyncSetScaleOverall(struct SiHdl *hdl, SPWfloat32 v)
132 | {
133 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
134 | return SPW_NO_ERROR;
135 | }
136 |
137 | enum SpwRetVal SPWAPI SiSyncGetScaleTx(struct SiHdl *hdl, SPWfloat32 *pv)
138 | {
139 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
140 | return SPW_NO_ERROR;
141 | }
142 |
143 | enum SpwRetVal SPWAPI SiSyncSetScaleTx(struct SiHdl *hdl, SPWfloat32 v)
144 | {
145 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
146 | return SPW_NO_ERROR;
147 | }
148 |
149 | enum SpwRetVal SPWAPI SiSyncGetScaleTy(struct SiHdl *hdl, SPWfloat32 *pv)
150 | {
151 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
152 |
153 | return SPW_NO_ERROR;
154 | }
155 |
156 | enum SpwRetVal SPWAPI SiSyncSetScaleTy(struct SiHdl *hdl, SPWfloat32 v)
157 | {
158 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
159 |
160 | return SPW_NO_ERROR;
161 | }
162 |
163 | enum SpwRetVal SPWAPI SiSyncGetScaleTz(struct SiHdl *hdl, SPWfloat32 *pv)
164 | {
165 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
166 | return SPW_NO_ERROR;
167 | }
168 |
169 | enum SpwRetVal SPWAPI SiSyncSetScaleTz(struct SiHdl *hdl, SPWfloat32 v)
170 | {
171 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
172 | return SPW_NO_ERROR;
173 | }
174 |
175 | enum SpwRetVal SPWAPI SiSyncGetScaleRx(struct SiHdl *hdl, SPWfloat32 *pv)
176 | {
177 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
178 |
179 | return SPW_NO_ERROR;
180 | }
181 |
182 | enum SpwRetVal SPWAPI SiSyncSetScaleRx(struct SiHdl *hdl, SPWfloat32 v)
183 | {
184 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
185 |
186 | return SPW_NO_ERROR;
187 | }
188 |
189 | enum SpwRetVal SPWAPI SiSyncGetScaleRy(struct SiHdl *hdl, SPWfloat32 *pv)
190 | {
191 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
192 | return SPW_NO_ERROR;
193 | }
194 |
195 | enum SpwRetVal SPWAPI SiSyncSetScaleRy(struct SiHdl *hdl, SPWfloat32 v)
196 | {
197 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
198 | return SPW_NO_ERROR;
199 | }
200 |
201 | enum SpwRetVal SPWAPI SiSyncGetScaleRz(struct SiHdl *hdl, SPWfloat32 *pv)
202 | {
203 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
204 |
205 | return SPW_NO_ERROR;
206 | }
207 |
208 | enum SpwRetVal SPWAPI SiSyncSetScaleRz(struct SiHdl *hdl, SPWfloat32 v)
209 | {
210 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
211 |
212 | return SPW_NO_ERROR;
213 | }
214 |
215 | enum SpwRetVal SPWAPI SiSyncInvokeAbsoluteFunction(struct SiHdl *hdl, SiSyncAbsFunctionNumber i)
216 | {
217 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
218 |
219 | return SPW_NO_ERROR;
220 | }
221 |
222 | enum SpwRetVal SPWAPI SiSyncSetButtonState(struct SiHdl *hdl, SPWuint32 bn_num, SiSyncButtonState state)
223 | {
224 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
225 |
226 | return SPW_NO_ERROR;
227 | }
--------------------------------------------------------------------------------
/siappdll/siappdll.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 | {E3AE0F7F-2BBD-4563-AE22-1A92E11630F0}
23 | siappdll
24 | Win32Proj
25 | 10.0.18362.0
26 |
27 |
28 |
29 | DynamicLibrary
30 | v143
31 | MultiByte
32 | true
33 |
34 |
35 | DynamicLibrary
36 | v141
37 | MultiByte
38 | false
39 |
40 |
41 | DynamicLibrary
42 | v143
43 | MultiByte
44 |
45 |
46 | DynamicLibrary
47 | v141
48 | MultiByte
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | <_ProjectFileVersion>12.0.21005.1
69 |
70 |
71 | $(SolutionDir)$(Configuration)\
72 | $(Configuration)\
73 | true
74 |
75 |
76 | true
77 |
78 |
79 | $(SolutionDir)$(Configuration)\
80 | $(Configuration)\
81 | false
82 |
83 |
84 | false
85 |
86 |
87 |
88 | Disabled
89 | $(SolutionDir);$(SolutionDir)\include;%(AdditionalIncludeDirectories);C:\Boost\include\boost-1_78
90 | WIN32;_DEBUG;_WINDOWS;_USRDLL;SIAPPDLL_EXPORTS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)
91 | true
92 | EnableFastChecks
93 | MultiThreadedDebugDLL
94 |
95 | Level3
96 | EditAndContinue
97 | 4996;%(DisableSpecificWarnings)
98 |
99 |
100 | dinput8.lib;dxguid.lib;comctl32.lib;ws2_32.lib;%(AdditionalDependencies);Shlwapi.lib
101 | siappdll.def
102 | true
103 | Windows
104 | MachineX86
105 | C:\Boost\lib
106 |
107 |
108 |
109 |
110 | Disabled
111 | $(SolutionDir);$(SolutionDir)\include;%(AdditionalIncludeDirectories)
112 | WIN32;_DEBUG;_WINDOWS;_USRDLL;SIAPPDLL_EXPORTS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)
113 | EnableFastChecks
114 | MultiThreadedDebugDLL
115 |
116 |
117 | Level3
118 | ProgramDatabase
119 | 4996;%(DisableSpecificWarnings)
120 |
121 |
122 | dinput8.lib;dxguid.lib;comctl32.lib;ws2_32.lib;%(AdditionalDependencies);Shlwapi.lib
123 | siappdll.def
124 | true
125 | Windows
126 |
127 |
128 |
129 |
130 | MaxSpeed
131 | true
132 | $(SolutionDir);$(SolutionDir)\include;%(AdditionalIncludeDirectories)
133 | WIN32;NDEBUG;_WINDOWS;_USRDLL;SIAPPDLL_EXPORTS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)
134 | MultiThreadedDLL
135 | true
136 |
137 | Level3
138 | ProgramDatabase
139 |
140 |
141 | dinput8.lib;dxguid.lib;comctl32.lib;ws2_32.lib;%(AdditionalDependencies);Shlwapi.lib
142 | siappdll.def
143 | true
144 | Windows
145 | true
146 | true
147 | MachineX86
148 |
149 |
150 |
151 |
152 | MaxSpeed
153 | true
154 | $(SolutionDir);$(SolutionDir)\include;%(AdditionalIncludeDirectories)
155 | WIN32;NDEBUG;_WINDOWS;_USRDLL;SIAPPDLL_EXPORTS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)
156 | MultiThreadedDLL
157 | true
158 |
159 |
160 | Level3
161 | ProgramDatabase
162 |
163 |
164 | dinput8.lib;dxguid.lib;comctl32.lib;ws2_32.lib;%(AdditionalDependencies);Shlwapi.lib
165 | siappdll.def
166 | true
167 | Windows
168 | true
169 | true
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
203 |
204 |
205 |
--------------------------------------------------------------------------------
/siappdll/src/siappdll.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | SpaceNavigatorEmulator - 3dconnexion-compatible siappdll.dll replacement
3 | Copyright (C) 2014 John Tsiombikas
4 | Copyright (C) 2015 Luke Nuttall
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 | #include "config.h"
20 | #include
21 | #include
22 | #include
23 | #include "siappdll.h"
24 | #include "siappdll_impl.h"
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include "log.h"
30 | #include "sock.h"
31 |
32 | #include "MinHook.h"
33 |
34 | #define SHAPE
35 | #define SHAPE_DELAY_MS 30
36 |
37 | extern "C" {
38 | typedef UINT(__stdcall* GETRAWINPUTDEVICEINFOW)(HANDLE, UINT, LPVOID, PUINT);
39 |
40 | GETRAWINPUTDEVICEINFOW fpOldGetRawInput = NULL;
41 |
42 | typedef UINT(WINAPI* GetDeviceList)(PRAWINPUTDEVICELIST pRawInputDeviceList, PUINT puiNumDevices, UINT cbSize);
43 |
44 | GetDeviceList fpOldGetDeviceList = NULL;
45 | }
46 |
47 | bool hookNext = false;
48 | UINT WINAPI DetourGetRawInputDeviceList(PRAWINPUTDEVICELIST pRawInputDeviceList, PUINT puiNumDevices, UINT cbSize)
49 | {
50 | if (hookNext)
51 | {
52 | LOG(TRACE) << "Faking GetRawInputDeviceList";
53 | hookNext = false;
54 | return 1;
55 | }
56 | else
57 | {
58 | return fpOldGetDeviceList(pRawInputDeviceList, puiNumDevices, cbSize);
59 | }
60 | }
61 |
62 | UINT WINAPI DetourGetRawInputDeviceInfoW(HANDLE hDevice, UINT uiCommand, LPVOID pData, PUINT pcbSize)
63 | {
64 | if (hookNext)
65 | {
66 | LOG(TRACE) << "Faking GetRawInputDeviceInfoW";
67 | hookNext = false;
68 | return 1;
69 | }
70 | else
71 | {
72 | return fpOldGetRawInput(hDevice, uiCommand, pData, pcbSize);
73 | }
74 | }
75 |
76 | int startHook()
77 | {
78 | // Initialize MinHook.
79 | if (MH_Initialize() != MH_OK)
80 | {
81 | return 1;
82 | }
83 |
84 | // Create a hook in disabled state.
85 | if (MH_CreateHook(&GetRawInputDeviceInfoW, &DetourGetRawInputDeviceInfoW,
86 | reinterpret_cast(&fpOldGetRawInput)) != MH_OK)
87 | {
88 | return 1;
89 | }
90 | if (MH_CreateHook(&GetRawInputDeviceList, &DetourGetRawInputDeviceList,
91 | reinterpret_cast(&fpOldGetDeviceList)) != MH_OK)
92 | {
93 | return 1;
94 | }
95 |
96 | // Enable the hook
97 | if (MH_EnableHook(&GetRawInputDeviceInfoW) != MH_OK)
98 | {
99 | LOG(ERROR) << "Could not hook GetRawInputDeviceInfoW";
100 | return 1;
101 | }
102 |
103 | // Enable the hook
104 | if (MH_EnableHook(&GetRawInputDeviceList) != MH_OK)
105 | {
106 | LOG(ERROR) << "Could not hook GetRawInputDeviceList";
107 | return 1;
108 | }
109 | return -1;
110 | }
111 |
112 | typedef struct {
113 | long data[7];
114 | } motion_t;
115 |
116 | std::deque m_queue;
117 |
118 | HWND tgt_wndw;
119 |
120 | HANDLE ghMutex = NULL;
121 | HANDLE hRcvThread = NULL;
122 | int sock_fd = -1;
123 |
124 |
125 | void clear_context(void)
126 | {
127 | // TODO: clear
128 | // space_ware_message
129 |
130 | sock_close(sock_fd);
131 | if (hRcvThread) {
132 | TerminateThread(hRcvThread, NULL);
133 | WaitForSingleObject(hRcvThread, INFINITE);
134 | CloseHandle(hRcvThread);
135 | }
136 | if (ghMutex)
137 | CloseHandle(ghMutex);
138 | }
139 |
140 | void collectMotionEvent(motion_t m)
141 | {
142 | WaitForSingleObject(ghMutex, INFINITE);
143 |
144 | m_queue.push_back(m);
145 |
146 | ReleaseMutex(ghMutex);
147 |
148 | int ret = PostMessage(tgt_wndw, space_ware_message, SI_MOTION_EVENT, 1);
149 | if (ret == 0)
150 | std::cout << "error " << GetLastError() << "\n";
151 | LOG(TRACE) << "message send";
152 | }
153 |
154 | DWORD WINAPI RcvThreadFunction(LPVOID lpParam)
155 | {
156 | int fd = *(int *)lpParam;
157 |
158 | #ifdef SHAPE
159 | ULONGLONG last = GetTickCount64();
160 | #endif
161 | motion_t m;
162 | memset(&m, 0, sizeof(motion_t));
163 |
164 | while (1)
165 | {
166 | int buf[8];
167 | int ret = sock_read(fd, (char*)buf, sizeof(buf));
168 | if (ret <= 0)
169 | break;
170 |
171 | #ifdef SHAPE
172 | ULONGLONG now = GetTickCount64();
173 |
174 | if ((now - last) > SHAPE_DELAY_MS) {
175 | long sum = 0;
176 | for (int i = 0; i < 6; i++)
177 | sum |= m.data[i];
178 | if (sum) {
179 | collectMotionEvent(m);
180 | memset(&m, 0, sizeof(motion_t));
181 | }
182 |
183 | last = now;
184 | }
185 | #endif
186 |
187 | if (buf[0] == 0)
188 | {
189 | for (int i = 0; i < 7; i++)
190 | #ifdef SHAPE
191 | m.data[i] += buf[i + 1];
192 | #else
193 | m.data[i] = buf[i + 1];
194 |
195 | collectMotionEvent(m);
196 | #endif
197 | }
198 |
199 | #if 1
200 | char out[128];
201 | int ocnt = 0;
202 |
203 | for (int i = 0; i < 7; i++)
204 | ocnt += snprintf(out + ocnt, sizeof(out) - ocnt, "%d ", buf[i]);
205 | ocnt += snprintf(out + ocnt, sizeof(out) - ocnt, "%u ", (unsigned int)buf[7]);
206 |
207 | LOG(TRACE) << out;
208 | #endif
209 | }
210 |
211 | return 0;
212 | }
213 |
214 | BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
215 | {
216 | switch (ul_reason_for_call)
217 | {
218 | case DLL_PROCESS_ATTACH:
219 | {
220 | LOG(INFO) << "Starting siappdll replacement";
221 |
222 | auto startedHook = startHook();
223 |
224 | LOG(INFO) << "Siappdll loaded: ";
225 | char buffer[MAX_PATH];
226 | if (!FAILED(::GetModuleFileName(::GetModuleHandle("siappdll.dll"), buffer, MAX_PATH)))
227 | {
228 | LOG(INFO) << "Loaded from: "<< buffer;
229 | }
230 |
231 | // We could set this byte as an alternative to hooking the device input functions
232 | // but it's more liable to blow up with different versions of the static libraries included
233 | // in apps using the space navigator sdk
234 | //byte* actualbRawInputFound3DxDevice = (byte *)0x413489;
235 | //*actualbRawInputFound3DxDevice = 1;
236 | }
237 | case DLL_THREAD_ATTACH:
238 | case DLL_THREAD_DETACH:
239 | case DLL_PROCESS_DETACH:
240 | break;
241 | }
242 | return TRUE;
243 | }
244 |
245 | enum SpwRetVal SPWAPI SiInitialize(void)
246 | {
247 | enum SpwRetVal ret = SPW_ERROR;
248 |
249 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
250 |
251 | sock_fd = sock_connect(SOCK_FILE);
252 | if (sock_fd < 0)
253 | {
254 | LOG(ERROR) << "connection to daemon failed";
255 | goto err;
256 | }
257 |
258 | if (!(space_ware_message = RegisterWindowMessage("SpaceWareMessage00")))
259 | {
260 | LOG(ERROR) << "failed to register window message";
261 | goto err;
262 | }
263 |
264 | ghMutex = CreateMutex(
265 | NULL, // default security attributes
266 | FALSE, // initially not owned
267 | NULL); // unnamed mutex
268 |
269 | if (ghMutex == NULL)
270 | {
271 | LOG(ERROR) << "CreateMutex error " << GetLastError();
272 | goto err;
273 | }
274 |
275 | hRcvThread = CreateThread(
276 | NULL, // default security attributes
277 | 0, // use default stack size
278 | RcvThreadFunction, // thread function name
279 | &sock_fd, // argument to thread function
280 | 0, // use default creation flags
281 | NULL); // returns the thread identifier
282 |
283 | if (!hRcvThread)
284 | {
285 | LOG(ERROR) << "failed to create thread";
286 | goto err;
287 | }
288 |
289 | initialised = true;
290 |
291 | return SPW_NO_ERROR;
292 |
293 | err:
294 | clear_context();
295 |
296 | return SPW_ERROR;
297 | }
298 |
299 | SPWbool SiIsInitialized()
300 | {
301 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
302 | return initialised;
303 | }
304 |
305 | void SPWAPI SiTerminate(void)
306 | {
307 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
308 |
309 | clear_context();
310 |
311 | initialised = false;
312 | }
313 |
314 | void SPWAPI SiGetLibraryInfo(SiVerInfo *info)
315 | {
316 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
317 | info->major = VER_MAJOR;
318 | info->minor = VER_MINOR;
319 | info->build = VER_BUILD;
320 | strcpy(info->version, VER_STR);
321 | info->data[0] = 0;
322 | }
323 |
324 | enum SpwRetVal SPWAPI SiGetDriverInfo(SiVerInfo *info)
325 | {
326 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
327 | info->major = VER_MAJOR;
328 | info->minor = VER_MINOR;
329 | info->build = VER_BUILD;
330 | strcpy(info->version, VER_STR);
331 | info->data[0] = 0;
332 |
333 | return SPW_NO_ERROR;
334 | }
335 |
336 | enum SpwRetVal SPWAPI SiGetDevicePort(int devid, SiDevPort *port)
337 | {
338 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
339 | port->devID = 0;
340 | port->devClass =
341 | port->devType = SI_SPACENAVIGATOR;
342 | strcpy(port->devName, "SpaceNavigatorEmulator");
343 | strcpy(port->portName, "Pretend Port");
344 | return SPW_NO_ERROR;
345 | }
346 |
347 | int SPWAPI SiGetNumDevices(void)
348 | {
349 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
350 | return 1;
351 | }
352 |
353 | int SPWAPI SiDeviceIndex(int idx)
354 | {
355 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
356 | return 0;
357 | }
358 |
359 | void SPWAPI SiOpenWinInit(SiOpenData *opendata, void *win)
360 | {
361 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
362 | opendata->win = win;
363 | }
364 |
365 | struct SiHdl *SPWAPI SiOpen(const char *appname, int devid, SiTypeMask *tmask, int mode, SiOpenData *opendata)
366 | {
367 | LOG(TRACE) << "SiOpen called for app: " << appname;
368 | struct SiHdl *si = new SiHdl();
369 |
370 | if (!si)
371 | {
372 | SpwErrorVal = SPW_ERROR;
373 | return 0;
374 | }
375 |
376 | si->opendata = *opendata;
377 | si->opendata.lib_flag = 1;
378 | si->opendata.trans_ctl = nullptr;
379 | // FIXME - get an actual process id.
380 | si->opendata.pid = 1;
381 |
382 | tgt_wndw = (HWND)opendata->win;
383 |
384 | SpwErrorVal = SPW_NO_ERROR;
385 | return si;
386 | }
387 |
388 | struct SiHdl* SPWAPI SiOpenPort(const char *pAppName, const SiDevPort *pPort, int mode, const SiOpenData *pData)
389 | {
390 | LOG(TRACE) << __FUNCTION__ << " passing to SiOpen";
391 | // FIXME - copy data instead on const cast
392 | return SiOpen(pAppName, 0, nullptr, mode, const_cast(pData));
393 | }
394 |
395 | enum SpwRetVal SPWAPI SiClose(struct SiHdl *si)
396 | {
397 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
398 |
399 | delete si;
400 | return SPW_NO_ERROR;
401 | }
402 |
403 | int SPWAPI SiGetDeviceID(struct SiHdl *si)
404 | {
405 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
406 | SpwErrorVal = SPW_NO_ERROR;
407 | return 0; /* TODO */
408 | }
409 |
410 | enum SpwRetVal SPWAPI SiGetDeviceImageFileName(struct SiHdl *si, char *name, unsigned long *maxlen)
411 | {
412 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
413 | name[0] = 0;
414 | *maxlen = 0;
415 | return SPW_NO_ERROR; /* TODO */
416 | }
417 |
418 | SpwRetVal SPWAPI SiGetDeviceInfo(struct SiHdl *si, SiDevInfo *info)
419 | {
420 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
421 | info->dev_type = SI_SPACENAVIGATOR;
422 | info->num_buttons = 2;
423 | info->num_degrees = 6;
424 | info->can_beep = 0;
425 | return SPW_NO_ERROR;
426 | }
427 |
428 | enum SpwRetVal SPWAPI SiGetDeviceName(struct SiHdl *si, SiDeviceName *name)
429 | {
430 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
431 | strcpy(name->name, "SpaceNavigatorEmulator");
432 | return SPW_NO_ERROR;
433 | }
434 |
435 |
436 | enum SpwRetVal SPWAPI SiGrabDevice(struct SiHdl *si, SPWbool exclusive)
437 | {
438 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
439 | return SPW_NO_ERROR;
440 | }
441 |
442 | enum SpwRetVal SPWAPI SiReleaseDevice(struct SiHdl *si)
443 | {
444 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
445 | return SPW_NO_ERROR;
446 | }
447 |
448 | enum SpwRetVal SPWAPI SiRezero(struct SiHdl *si)
449 | {
450 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
451 | return SPW_NO_ERROR;
452 | }
453 |
454 | enum SpwRetVal SPWAPI SiBeep(struct SiHdl *si, char *str)
455 | {
456 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
457 | return SPW_NO_ERROR;
458 | }
459 |
460 | enum SpwRetVal SPWAPI SiSetLEDs(struct SiHdl *si, unsigned long mask)
461 | {
462 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
463 | return SPW_NO_ERROR;
464 | }
465 |
466 | enum SpwRetVal SPWAPI SiSetUiMode(struct SiHdl *si, unsigned long mode)
467 | {
468 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
469 | return SPW_NO_ERROR;
470 | }
471 |
472 | #define CALL_CB(cb, od, evdata, ev) cb.func(od, evdata, ev, cb.cls)
473 |
474 | int SPWAPI SiDispatch(struct SiHdl *si, SiGetEventData *data, SiSpwEvent *ev, SiSpwHandlers *handlers)
475 | {
476 | LOG(TRACE) << "Stub called: " << __FUNCTION__ << " - event: " << ev->type;
477 |
478 | if (handlers != nullptr)
479 | {
480 | switch (ev->type) {
481 | case SI_BUTTON_EVENT:
482 | return CALL_CB(handlers->button, &si->opendata, data, ev);
483 | case SI_MOTION_EVENT:
484 | if (handlers->motion.func != nullptr)
485 | return CALL_CB(handlers->motion, &si->opendata, data, ev);
486 | case SI_COMBO_EVENT:
487 | return CALL_CB(handlers->combo, &si->opendata, data, ev);
488 | case SI_ZERO_EVENT:
489 | return CALL_CB(handlers->zero, &si->opendata, data, ev);
490 | default:
491 | break;
492 | }
493 | }
494 | return 0;
495 | }
496 |
497 | void SPWAPI SiGetEventWinInit(SiGetEventData *evdata, unsigned int msg, unsigned int wparam, long lparam)
498 | {
499 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
500 | if (evdata == nullptr)
501 | {
502 | LOG(ERROR) << __FUNCTION__ << " called with null pointer for event storage";
503 | }
504 | evdata->msg = msg;
505 | evdata->lparam = lparam;
506 | evdata->wparam = wparam;
507 | }
508 |
509 | SpwRetVal SPWAPI SiGetEvent(struct SiHdl *si, int flags, const SiGetEventData *data, SiSpwEvent *ev)
510 | {
511 | LOG(TRACE) << "called: " << __FUNCTION__;
512 |
513 | // If we weren't given a valid pointer, we return bad value.
514 | if (!ev || !si || !data)
515 | return SI_BAD_VALUE;
516 |
517 | WaitForSingleObject(ghMutex, INFINITE);
518 | bool empty = m_queue.empty();
519 | ReleaseMutex(ghMutex);
520 | if (empty)
521 | return SI_NOT_EVENT;
522 |
523 | if (data->msg == space_ware_message)
524 | {
525 | long buf[7];
526 | std::deque ::size_type size;
527 |
528 | WaitForSingleObject(ghMutex, INFINITE);
529 |
530 | motion_t m = m_queue.front();
531 | memcpy(buf, m.data, sizeof(buf));
532 |
533 | m_queue.pop_front();
534 |
535 | size = m_queue.size();
536 |
537 | ReleaseMutex(ghMutex);
538 |
539 | LOG(TRACE) << "Queue size: " << size;
540 |
541 | // completely fake an event
542 | if (data->wparam == SI_MOTION_EVENT)
543 | {
544 | ev->type = data->wparam;
545 | ev->u.spw_data.button.last = 0;
546 | ev->u.spw_data.button.current = 0;
547 | ev->u.spw_data.button.release = 0;
548 | ev->u.spw_data.button.pressed = 0;
549 |
550 | ev->u.spw_data.motion[0] = buf[0];
551 | ev->u.spw_data.motion[1] = buf[1];
552 | ev->u.spw_data.motion[2] = buf[2];
553 | ev->u.spw_data.motion[3] = buf[3];
554 | ev->u.spw_data.motion[4] = buf[4];
555 | ev->u.spw_data.motion[5] = buf[5];
556 |
557 | ev->u.spw_data.period = buf[6];
558 | #if 1 // maybe not needed, but original test program - jet.exe reaction to long period is not good, fusion360 reaction is good
559 | if (ev->u.spw_data.period > 500)
560 | ev->u.spw_data.period = 0;
561 | #endif
562 |
563 | if (data->wparam == SI_MOTION_EVENT)
564 | hookNext = true;
565 | }
566 | else if (data->wparam == SI_BUTTON_EVENT)
567 | {
568 | #if 0
569 | ev->type = data->wparam;
570 | ev->u.spw_data.button.last = record.buttonData.last;
571 | ev->u.spw_data.button.current = record.buttonData.current;
572 | ev->u.spw_data.button.release = record.buttonData.release;
573 | ev->u.spw_data.button.pressed = record.buttonData.pressed;
574 | ev->u.spw_data.motion[0] = 0;
575 | ev->u.spw_data.motion[1] = 0;
576 | ev->u.spw_data.motion[2] = 0;
577 | ev->u.spw_data.motion[3] = 0;
578 | ev->u.spw_data.motion[4] = 0;
579 | ev->u.spw_data.motion[5] = 0;
580 | ev->u.spw_data.period = 0;
581 | #endif
582 | }
583 | else if (data->wparam == SI_BUTTON_PRESS_EVENT || data->wparam == SI_BUTTON_RELEASE_EVENT)
584 | {
585 | ev->type = data->wparam;
586 | ev->u.hwButtonEvent.buttonNumber = data->lparam;
587 | }
588 |
589 | return SI_IS_EVENT;
590 | }
591 | else
592 | {
593 | return SI_NOT_EVENT;
594 | }
595 | }
596 |
597 | SpwRetVal SPWAPI SiPeekEvent(struct SiHdl *si, int flags, const SiGetEventData *data, SiSpwEvent *ev)
598 | {
599 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
600 |
601 | // FIXME - implement
602 | return SPW_NO_ERROR;
603 | }
604 |
605 | SPWbool SPWAPI SiIsSpaceWareEvent(const SiGetEventData *data, struct SiHdl *si)
606 | {
607 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
608 | return data->msg == space_ware_message;
609 | }
610 |
611 | int SPWAPI SiButtonPressed(SiSpwEvent *ev)
612 | {
613 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
614 |
615 | long pressed = ev->u.spw_data.button.pressed;
616 |
617 | for (unsigned int i = 0; i < 32; i++)
618 | {
619 | if ((1 << i) & pressed)
620 | {
621 | return i;
622 | }
623 | }
624 | return 0;
625 | }
626 |
627 | int SPWAPI SiButtonReleased(SiSpwEvent *ev)
628 | {
629 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
630 |
631 | long released = ev->u.spw_data.button.release;
632 |
633 | for (unsigned int i = 0; i < 32; i++)
634 | {
635 | if ((1 << i) & released)
636 | {
637 | return i;
638 | }
639 | }
640 | return 0;
641 | }
642 |
643 | enum SpwRetVal SPWAPI SiGetButtonName(struct SiHdl *si, unsigned long bnum, SiButtonName *name)
644 | {
645 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
646 | strcpy(name->name, "Smoooth buttony text");
647 | return SPW_NO_ERROR;
648 | }
649 |
650 | void *SPWAPI SiGetCompanyIcon(void)
651 | {
652 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
653 |
654 | return NULL;
655 | }
656 |
657 | enum SpwRetVal SPWAPI SiGetCompanyLogoFileName(char *name, unsigned long *maxlen)
658 | {
659 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
660 |
661 | return SPW_ERROR;
662 | }
663 |
664 |
665 | static const char *errnames[] = {
666 | "no error",
667 | "error -- function failed",
668 | "invalid 3DxWare handle",
669 | "invalid device ID",
670 | "invalid argument value",
671 | "event is a 3DxWare event",
672 | "skip this 3DxWare event",
673 | "event is not a 3DxWare event",
674 | "3DxWare driver is not running",
675 | "3DxWare driver is not responding",
676 | "the function is unsupported by this version",
677 | "3DxWare Input Library is uninitialized",
678 | "incorrect driver for this 3DxWare version",
679 | "internal 3DxWare error"
680 | };
681 |
682 | const char *SPWAPI SpwErrorString(enum SpwRetVal err)
683 | {
684 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
685 | return errnames[(int)err];
686 | }
687 |
688 | /* deprecated */
689 | enum SpwRetVal SiSetTypeMask(SiTypeMask *mask, int type1, ...)
690 | {
691 | LOG(TRACE) << "Stub called: " << __FUNCTION__;
692 | return SPW_NO_ERROR;
693 | }
694 |
695 |
--------------------------------------------------------------------------------