Blender  V3.3
GHOST_NDOFManagerCocoa.mm
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #define DEBUG_NDOF_DRIVER false
4 
6 #include "GHOST_SystemCocoa.h"
7 
8 #include <dlfcn.h>
9 #include <stdint.h>
10 
11 #if DEBUG_NDOF_DRIVER
12 # include <cstdio>
13 #endif
14 
15 // static callback functions need to talk to these objects:
18 
19 static uint16_t clientID = 0;
20 
21 static bool driver_loaded = false;
22 static bool has_old_driver =
23  false; // 3Dconnexion drivers before 10 beta 4 are "old", not all buttons will work
24 static bool has_new_driver =
25  false; // drivers >= 10.2.2 are "new", and can process events on a separate thread
26 
27 // replicate just enough of the 3Dx API for our uses, not everything the driver provides
28 
29 #define kConnexionClientModeTakeOver 1
30 #define kConnexionMaskAll 0x3fff
31 #define kConnexionMaskAllButtons 0xffffffff
32 #define kConnexionCmdHandleButtons 2
33 #define kConnexionCmdHandleAxis 3
34 #define kConnexionCmdAppSpecific 10
35 #define kConnexionMsgDeviceState '3dSR'
36 #define kConnexionCtlGetDeviceID '3did'
37 
38 #pragma pack(push, 2) // just this struct
47  uint16_t buttons8; // obsolete! (pre-10.x drivers)
48  int16_t axis[6]; // tx, ty, tz, rx, ry, rz
51 };
52 #pragma pack(pop)
53 
54 // callback functions:
57 typedef void (*MessageHandler)(uint32_t, uint32_t msg_type, void *msg_arg);
58 
59 // driver functions:
64  const char *name,
65  uint16_t mode,
66  uint32_t mask);
70  uint32_t message,
71  int32_t param,
72  int32_t *result);
73 
74 #define DECLARE_FUNC(name) name##_ptr name = NULL
75 
76 DECLARE_FUNC(SetConnexionHandlers);
77 DECLARE_FUNC(InstallConnexionHandlers);
78 DECLARE_FUNC(CleanupConnexionHandlers);
79 DECLARE_FUNC(RegisterConnexionClient);
80 DECLARE_FUNC(SetConnexionClientButtonMask);
81 DECLARE_FUNC(UnregisterConnexionClient);
82 DECLARE_FUNC(ConnexionClientControl);
83 
84 static void *load_func(void *module, const char *func_name)
85 {
86  void *func = dlsym(module, func_name);
87 
88 #if DEBUG_NDOF_DRIVER
89  if (func) {
90  printf("'%s' loaded :D\n", func_name);
91  }
92  else {
93  printf("<!> %s\n", dlerror());
94  }
95 #endif
96 
97  return func;
98 }
99 
100 #define LOAD_FUNC(name) name = (name##_ptr)load_func(module, #name)
101 
102 static void *module; // handle to the whole driver
103 
105 {
106  if (driver_loaded) {
107  return true;
108  }
109 
110  module = dlopen("/Library/Frameworks/3DconnexionClient.framework/3DconnexionClient",
111  RTLD_LAZY | RTLD_LOCAL);
112 
113  if (module) {
114  LOAD_FUNC(SetConnexionHandlers);
115 
116  if (SetConnexionHandlers != NULL) {
117  driver_loaded = true;
118  has_new_driver = true;
119  }
120  else {
121  LOAD_FUNC(InstallConnexionHandlers);
122 
123  driver_loaded = (InstallConnexionHandlers != NULL);
124  }
125 
126  if (driver_loaded) {
127  LOAD_FUNC(CleanupConnexionHandlers);
128  LOAD_FUNC(RegisterConnexionClient);
129  LOAD_FUNC(SetConnexionClientButtonMask);
130  LOAD_FUNC(UnregisterConnexionClient);
131  LOAD_FUNC(ConnexionClientControl);
132 
133  has_old_driver = (SetConnexionClientButtonMask == NULL);
134  }
135  }
136 #if DEBUG_NDOF_DRIVER
137  else {
138  printf("<!> %s\n", dlerror());
139  }
140 
141  printf("loaded: %s\n", driver_loaded ? "YES" : "NO");
142  printf("old: %s\n", has_old_driver ? "YES" : "NO");
143  printf("new: %s\n", has_new_driver ? "YES" : "NO");
144 #endif
145 
146  return driver_loaded;
147 }
148 
149 static void unload_driver()
150 {
151  dlclose(module);
152 }
153 
154 static void DeviceAdded(uint32_t unused)
155 {
156 #if DEBUG_NDOF_DRIVER
157  printf("ndof: device added\n");
158 #endif
159 
160  // determine exactly which device is plugged in
161  int32_t result;
162  ConnexionClientControl(clientID, kConnexionCtlGetDeviceID, 0, &result);
163  int16_t vendorID = result >> 16;
164  int16_t productID = result & 0xffff;
165 
166  ndof_manager->setDevice(vendorID, productID);
167 }
168 
169 static void DeviceRemoved(uint32_t unused)
170 {
171 #if DEBUG_NDOF_DRIVER
172  printf("ndof: device removed\n");
173 #endif
174 }
175 
176 static void DeviceEvent(uint32_t unused, uint32_t msg_type, void *msg_arg)
177 {
178  if (msg_type == kConnexionMsgDeviceState) {
180 
181  // device state is broadcast to all clients; only react if sent to us
182  if (s->client == clientID) {
183  // TODO: is s->time compatible with GHOST timestamps? if so use that instead.
185 
186  switch (s->command) {
188  // convert to blender view coordinates
189  const int t[3] = {s->axis[0], -(s->axis[2]), s->axis[1]};
190  const int r[3] = {-(s->axis[3]), s->axis[5], -(s->axis[4])};
191 
194 
196  break;
197  }
199  int button_bits = has_old_driver ? s->buttons8 : s->buttons;
200 #ifdef DEBUG_NDOF_BUTTONS
201  printf("button bits: 0x%08x\n", button_bits);
202 #endif
203  ndof_manager->updateButtons(button_bits, now);
205  break;
206  }
207 #if DEBUG_NDOF_DRIVER
209  printf("ndof: app-specific command, param = %hd, value = %d\n", s->param, s->value);
210  break;
211 
212  default:
213  printf("ndof: mystery device command %d\n", s->command);
214 #endif
215  }
216  }
217  }
218 }
219 
221 {
222  if (load_driver_functions()) {
223  // give static functions something to talk to:
224  ghost_system = dynamic_cast<GHOST_SystemCocoa *>(&sys);
225  ndof_manager = this;
226 
227  uint16_t error;
228  if (has_new_driver) {
229  const bool separate_thread = false; // TODO: rework Mac event handler to allow this
230  error = SetConnexionHandlers(DeviceEvent, DeviceAdded, DeviceRemoved, separate_thread);
231  }
232  else {
233  error = InstallConnexionHandlers(DeviceEvent, DeviceAdded, DeviceRemoved);
234  }
235 
236  if (error) {
237 #if DEBUG_NDOF_DRIVER
238  printf("ndof: error %d while setting up handlers\n", error);
239 #endif
240  return;
241  }
242 
243  // Pascal string *and* a four-letter constant. How old-skool.
244  clientID = RegisterConnexionClient(
245  'blnd', "\007blender", kConnexionClientModeTakeOver, kConnexionMaskAll);
246 
247  if (!has_old_driver) {
248  SetConnexionClientButtonMask(clientID, kConnexionMaskAllButtons);
249  }
250  }
251 }
252 
254 {
255  if (driver_loaded) {
256  UnregisterConnexionClient(clientID);
257  CleanupConnexionHandlers();
258  unload_driver();
259 
260  ghost_system = NULL;
261  ndof_manager = NULL;
262  }
263 }
264 
266 {
267  return driver_loaded;
268 }
void(* CleanupConnexionHandlers_ptr)()
static GHOST_NDOFManager * ndof_manager
static void DeviceAdded(uint32_t unused)
uint16_t(* RegisterConnexionClient_ptr)(uint32_t signature, const char *name, uint16_t mode, uint32_t mask)
int16_t(* InstallConnexionHandlers_ptr)(MessageHandler, AddedHandler, RemovedHandler)
#define kConnexionCmdAppSpecific
int16_t(* SetConnexionHandlers_ptr)(MessageHandler, AddedHandler, RemovedHandler, bool)
void(* SetConnexionClientButtonMask_ptr)(uint16_t clientID, uint32_t buttonMask)
#define kConnexionCmdHandleButtons
static bool load_driver_functions()
void(* RemovedHandler)(uint32_t)
static void unload_driver()
static void * load_func(void *module, const char *func_name)
static void * module
static bool has_old_driver
static uint16_t clientID
static void DeviceEvent(uint32_t unused, uint32_t msg_type, void *msg_arg)
static void DeviceRemoved(uint32_t unused)
void(* MessageHandler)(uint32_t, uint32_t msg_type, void *msg_arg)
static bool driver_loaded
#define DECLARE_FUNC(name)
#define kConnexionMsgDeviceState
#define kConnexionMaskAll
static bool has_new_driver
#define kConnexionCtlGetDeviceID
#define kConnexionCmdHandleAxis
#define kConnexionMaskAllButtons
void(* AddedHandler)(uint32_t)
void(* UnregisterConnexionClient_ptr)(uint16_t clientID)
#define kConnexionClientModeTakeOver
#define LOAD_FUNC(name)
int16_t(* ConnexionClientControl_ptr)(uint16_t clientID, uint32_t message, int32_t param, int32_t *result)
static GHOST_SystemCocoa * ghost_system
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
GHOST_NDOFManagerCocoa(GHOST_System &)
void updateButtons(int button_bits, uint64_t time)
void updateTranslation(const int t[3], uint64_t time)
void updateRotation(const int r[3], uint64_t time)
bool setDevice(unsigned short vendor_id, unsigned short product_id)
uint64_t getMilliSeconds() const
SyclQueue void void size_t num_bytes void
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
static void error(const char *str)
Definition: meshlaplacian.c:51
signed short int16_t
Definition: stdint.h:76
unsigned short uint16_t
Definition: stdint.h:79
unsigned int uint32_t
Definition: stdint.h:80
signed int int32_t
Definition: stdint.h:77
unsigned char uint8_t
Definition: stdint.h:78
unsigned __int64 uint64_t
Definition: stdint.h:90