Developing using the OS X driver

Questions and answers about 3Dconnexion devices on macOS.

Moderator: Moderators

Post Reply
stew
Posts: 10
Joined: Wed Dec 20, 2006 9:34 am

Developing using the OS X driver

Post by stew »

I noticed that the OS X driver beta comes with a few headers in /System/Library/3DconnexionClient.framework that look very inviting. Is there any documentation or a OS X beta SDK available?

One thing I tried out with the beta drivers is a C program like this:

Code: Select all

void AddedDevice(io_connect_t connection)
{
	printf("added device\n");
}
void RemovedDevice(io_connect_t connection)
{
	printf("removed device\n");
}
void HandleMessage(io_connect_t connection, natural_t messageType, void *messageArgument)
{
	printf("received message\n");
	return;
}

int main(int argc, char *argv[])
{
	OSErr err = InstallConnexionHandlers (HandleMessage, AddedDevice, RemovedDevice);
	UInt32 signature = kConnexionClientWildcard;
	UInt8 *name = "";
	UInt16 mode = kConnexionClientModePlugin;
	UInt32 mask = kConnexionMaskAll;
	UInt16 myID = RegisterConnexionClient(signature, name, mode, mask);
	CFRunLoopRun();
	UnregisterConnexionClient(myID);
	CleanupConnexionHandlers();
	return 0;
}
This code gives me correct messages when I plug or unplug my SpaceNavigator, but I was unable to read any axis information from it. The only time HandleMessage gets called is when I press a button that has been assigned in the prefs panel.

Any hints on how I can get access to the axis data?
flomotan
Moderator
Moderator
Posts: 287
Joined: Mon Jan 08, 2007 3:37 pm

Post by flomotan »

It's good to see the developer community taking an interest in this :).

The SDK is not officially released and is subject to change without notice. It may not even exist when the final driver is released. In other words, you're on your own here. Having given the mandatory disclaimer, here's how you can get axis data:

Call RegisterConnexionClient with mode = kConnexionClientModeTakeOver and mask = kConnexionMaskAxis.

In your message handler, process the incoming message using code similar to this.

Code: Select all

static void 
messageHandlerProc(io_connect_t connection, natural_t messageType, void *messageArgument)
{
	ConnexionDeviceStatePtr msg;

	msg = (ConnexionDeviceStatePtr)messageArgument;
	
	switch(messageType)
	{
		case kConnexionMsgDeviceState:
			/* Device state messages are broadcast to all clients.  It is up to
			 * the client to figure out if the message is meant for them. This
			 * is done by comparing the "client" id sent in the message to our
			 * assigned id when the connection to the driver was established.
			 * 
			 */
			switch (msg->command)
			{
				case kConnexionCmdHandleAxis:
					// msg->axis[0] .. [5] contain X, Y, Z, Rx, Ry, Rz data                            
					break;
                    
                        
				case kConnexionCmdHandleButtons:
					// msg->value is the button state 
					// msg->buttons is the button ID
					break;						
			}
			break;

		default:
			// other messageTypes can happen and should be ignored
			break;
	}
}
stew
Posts: 10
Joined: Wed Dec 20, 2006 9:34 am

Post by stew »

Thanks a lot!
wave
Posts: 2
Joined: Tue Jan 16, 2007 10:25 am

trying to develop with Cocoa

Post by wave »

Thanks for the info about talking to the device. One nit - on my system, the framework got installed in /Library/Frameworks/, not /System/Library/Frameworks - I assume that's correct?

Also, like the other poster, my add and remove device procs get called, but I don't get anything sent to the handle message one - I twist the Navigator, press buttons, etc - nothing.

Any ideas?

In my case, I'm developing with Objective-C/Cocoa, and have a simple app with a class that looks like this:

#import <Cocoa>
#import <3DconnexionClient>


@interface MyController : NSObject
{
UInt16 _myID;
}
@end


#import "MyController.h"

@implementation MyController

static void
HandleMessage(io_connect_t connection, natural_t messageType, void *messageArgument) {

ConnexionDeviceStatePtr msg = (ConnexionDeviceStatePtr)messageArgument;

switch(messageType) {
case kConnexionMsgDeviceState:
/* Device state messages are broadcast to all clients. It is up to
* the client to figure out if the message is meant for them. This
* is done by comparing the "client" id sent in the message to our
* assigned id when the connection to the driver was established.
*
*/
switch (msg->command)
{
case kConnexionCmdHandleAxis:
// msg->axis[0] .. [5] contain X, Y, Z, Rx, Ry, Rz data
{
SInt16 x = msg->axis[0];
SInt16 y = msg->axis[1];
SInt16 z = msg->axis[2];
SInt16 Rx = msg->axis[3];
SInt16 Ry = msg->axis[4];
SInt16 Rz = msg->axis[5];

NSLog(@"x, y, z == (%hi, %hi, %hi) Rx, Ry, Rz == (%hi, %hi, %hi)", x, y, z, Rx, Ry, Rz);
}
break;


case kConnexionCmdHandleButtons:
// msg->value is the button state
// msg->buttons is the button ID
{
SInt32 buttonState = msg->value;
UInt16 buttonID = msg->buttons;
NSLog(@"button %hu pressed - value is %d", buttonID, buttonState);
}
break;
}
break;

default:
// other messageTypes can happen and should be ignored
break;
}
}

static void
AddedDevice(io_connect_t connection) {
NSLog(@"added device %p", connection);
}

static void
RemovedDevice(io_connect_t connection) {
NSLog(@"removed device %p", connection);
}


- (void)awakeFromNib {
OSErr err = InstallConnexionHandlers(HandleMessage, AddedDevice, RemovedDevice);
if (err == noErr) {
UInt32 signature = kConnexionClientWildcard;
UInt16 mode = kConnexionClientModePlugin;
UInt32 mask = kConnexionMaskAll;
_myID = RegisterConnexionClient(signature, NULL, mode, mask);
NSLog(@"installed handlers for 3Dconnexion Space Navigator and registed client : %hi", _myID);

} else {
NSLog(@"problem installing handlers for 3Dconnexion Space Navigator : %d", err);
}
}

- (void)dealloc {
if (_myID) {
UnregisterConnexionClient(_myID);
CleanupConnexionHandlers();
}
[super dealloc];
}

@end
flomotan
Moderator
Moderator
Posts: 287
Joined: Mon Jan 08, 2007 3:37 pm

Post by flomotan »

/Library/Frameworks is the recommended place for 3rd party frameworks.

Call RegisterConnexionClient with mode = kConnexionClientModeTakeOver and mask = kConnexionMaskAxis. This should resolve your issue.

Also, as much as possible, do not use kConnexionClientWildcard as the signature. Instead, provide the 32bit signature you have assigned for your application. This will allow you create specific settings for your application in our preference pane. Just use "Add Application..." to add your app.
wave
Posts: 2
Joined: Tue Jan 16, 2007 10:25 am

Post by wave »

Thanks.

We had figured out the kConnexionClientModeTakeOver but the other info is very useful.

Especially the Wildcard one - I was wondering why my app was getting called when I rotated the device in SketchUp :-)

We're doing great now. My one nit is that when I install the freshly downloaded driver on a machine, it asks to check for a newer one, and says that 0.1.0 is available, which is newer than 0.1 (or vice versa). If I let it get it, it takes to the same download page.

I appreciate the check, but the logic currently seems broken.
flomotan
Moderator
Moderator
Posts: 287
Joined: Mon Jan 08, 2007 3:37 pm

Post by flomotan »

Glad to hear you're up and running.

Thanks for pointing out the issue with version check. It's now fixed and will be part of our next release.
GregVDS
Posts: 18
Joined: Wed Feb 21, 2007 3:11 am
Location: Bruxelles

Post by GregVDS »

Where do I find the Mac Beta SDK please?

All the best,

GregVDS
All the best,

GregVDS
JiriHnidek
Posts: 1
Joined: Thu Mar 15, 2007 5:06 am

Simple code example

Post by JiriHnidek »

Hi,
this is my first post here. This is very simple c code (it only prints some debuging informations to stdout, but it can be very good begining and tutorial for any mac os x coder):

Code: Select all

#include <stdio.h>
#include <MacTypes.h>
#include <ConnexionClient.h>
#include <ConnexionClientAPI.h>

static void AddedDevice(io_connect_t connection) 
{ 
	printf("added device\n"); 
} 
static void RemovedDevice(io_connect_t connection) 
{ 
	printf("removed device\n"); 
} 
static void HandleMessage(io_connect_t connection, natural_t messageType, void *messageArgument) 
{
	ConnexionDeviceStatePtr msg;

	msg = (ConnexionDeviceStatePtr)messageArgument;

	switch(messageType) {
		case kConnexionMsgDeviceState:
			switch (msg->command) {
				case kConnexionCmdHandleAxis:
					printf("%d, %d, %d, %d, %d, %d\n",
							msg->axis[0], msg->axis[2], msg->axis[2],
							msg->axis[3], msg->axis[4], msg->axis[5]);
					break;
				case kConnexionCmdHandleButtons:
					printf("msg->value: %d\n", msg->value);
					printf("msg->buttons: %d\n", msg->buttons);
					break;
			}
			break;
	}
} 

int main(int argc, char *argv[]) 
{ 
	OSErr err = InstallConnexionHandlers (HandleMessage, AddedDevice, RemovedDevice); 
	UInt32 signature = kConnexionClientWildcard; 
	UInt8 *name = ""; 
	UInt16 mode = kConnexionClientModeTakeOver; /*kConnexionClientModePlugin;*/ 
	UInt32 mask = kConnexionMaskAxis; /*kConnexionMaskAll;*/ 
	UInt16 myID = RegisterConnexionClient(signature, name, mode, mask); 
	CFRunLoopRun(); 
	UnregisterConnexionClient(myID); 
	CleanupConnexionHandlers(); 
	return 0; 
} 
You will probably need Makefile too:

Code: Select all

CC=gcc
CFLAGS=-I /Library/Frameworks/3DconnexionClient.framework/Versions/Current/Headers/ -I /System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers
LFLAGS=-framework 3DconnexionClient -framework Carbon

all: 3dconn

3dconn: 3dconn.o
        ${CC} -o 3dconn ${LFLAGS} 3dconn.o 

3dconn.o: 3dconn.c
        ${CC} -c ${CFLAGS} -o 3dconn.o 3dconn.c

clean:
        rm -f *.o *~ 3dconn
I guess, that uou will need to remove white spaces with tabs in makefile.
Snow123
Posts: 3
Joined: Fri Mar 28, 2008 1:16 am
Contact:

Post by Snow123 »

This code gives me correct messages when I plug or unplug my SpaceNavigator, but I was unable to read any axis information from it. The only time HandleMessage gets called is when I press a button that has been assigned in the prefs panel.
flomotan
Moderator
Moderator
Posts: 287
Joined: Mon Jan 08, 2007 3:37 pm

Post by flomotan »

An official SDK with documentation for OS X is available at http://www.3dconnexion.com/support/sdk.php
Post Reply