diff --git a/CHANGELOG b/CHANGELOG index e5f6c1c..c395cca 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +2023-12-13 Jan Ciger + * 0.14 + - Support for SpaceMouse Enterprise + - Fixed crashes if device reports more than 32 buttons/6 axes + 2021-04-02 Jan Ciger * 0.13 - Support for joystick hats as extra axes (thanks @zi-ree) diff --git a/README.md b/README.md index f3f2928..07b846b 100644 --- a/README.md +++ b/README.md @@ -23,14 +23,21 @@ Currently supported are the following devices (VID:PID): * 0x256f:0xc62f SpaceMouse Wireless (receiver) (untested) * 0x256f:0xc631 SpaceMouse Wireless (untested) * 0x256f:0xc632 SpaceMouse Pro Wireless (untested) + * 0x256f:0xc633 SpaceMouse Enterprise (tested, works) * 0x256f:0xc635 SpaceMouse Compact (untested - from Kai Werthwein < https://github.com/KaiWerthwein > The following devices were contributed by Ricky Curtice (http://rwcproductions.com/): (https://bitbucket.org/lindenlab/3p-libndofdev-linux/pull-request/1/open-277-linux-support-for-spacemousepro/diff) -CADMan, all SpaceMice (classic & wireless) except SpaceMouse Pro (non-wireless), SpaceNavigator for Notebooks +CADMan, SpaceM (classic & wireless) except SpaceMouse Pro +(non-wireless) and SpaceMouse Entreprise, SpaceNavigator for Notebooks -The devices marked as "untested" are expected to work and their VID:PIDs were sent to me by external contributors. I haven't tested them personally because I don't have that hardware, they could work, could be completely broken or anything inbetween. Caveat emptor. However, please do report any working or not working devices from the list above - that's only way to get the problems fixed. +The devices marked as "untested" are expected to work and their +VID:PIDs were sent to me by external contributors. I haven't tested +them personally because I don't have that hardware, they could work, +could be completely broken or anything in-between. Caveat +emptor. However, please do report any working or not working devices +from the list above - that's the only way to get the problems fixed. In addition, the library supports every joystick/gamepad device supported by the SDL library. SDL2 is supported by passing a flag to @@ -46,10 +53,15 @@ This library is a messy hack emulating the proprietary 3Dconnexion SDK, in order client integration. If you are looking to integrate support for these devices into a new application, a much better solution is to use the event interface directly. An example of how to do this can be found here: - * http://janoc.rd-h.com/files/software/linux/spacenav/spacenavig.c + * http://jciger.com/files/software/linux/spacenav/spacenavig.c If you are building a virtual reality application, then the best option is to use the VRPN library: * http://www.cs.unc.edu/Research/vrpn/ VRPN supports all the devices above and many more in a transparent and abstract manner, so you don't have -to add support for each different interaction device or tracker specially. +to add support for each different interaction device or tracker +specially. + +Another option simulating the official 3DConnexion driver is the +Spacenav project: + * https://spacenav.sourceforge.net/ diff --git a/ndofdev.c b/ndofdev.c index b4e5c53..ba5e943 100644 --- a/ndofdev.c +++ b/ndofdev.c @@ -63,6 +63,12 @@ // turn its LED off in the ndof_cleanup() function :( static int spacenav_fd = -1; +// SpaceMouse button remapping table - SpaceMouse Enterprise has only +// 32 buttons but reports 9bit button codes, likely for compatibility +// with old hw. +#define SPACE_MOUSE_BUTTON_SPACE 256 +static long SPACE_MOUSE_BUTTON_MAPPING[SPACE_MOUSE_BUTTON_SPACE]; + const int SPACE_NAVIG_THRESHOLD = 20; // minimum change threshold typedef struct @@ -132,7 +138,8 @@ int ndof_init_first(NDOF_Device *in_out_dev, void *param) (ID.product == 0xc62E) || // SpaceMouse Wireless (cable) (untested) (ID.product == 0xc62F) || // SpaceMouse Wireless (receiver) (untested) (ID.product == 0xc631) || // Spacemouse Wireless (untested) - (ID.product == 0xc632) || // SpacemousePro Wireless (untested) + (ID.product == 0xc632) || // Spacemouse Pro Wireless (untested) + (ID.product == 0xc633) || // Spacemouse Enterprise (ID.product == 0xc635) || // Spacemouse Compact (untested) 0 ) @@ -218,8 +225,12 @@ int ndof_init_first(NDOF_Device *in_out_dev, void *param) perror("Failed to obtain the number of buttons for device:\n"); } - in_out_dev->axes_count = axes_count; - in_out_dev->btn_count = button_count; + // clamp number of axes & buttons to what is actually + // supported by the original SDK to avoid corrupting + // memory. 3DConnexion devices routinely report 255+ buttons + // even though they have only 32. + in_out_dev->axes_count = (axes_count <= NDOF_MAX_AXES_COUNT) ? axes_count : NDOF_MAX_AXES_COUNT; + in_out_dev->btn_count = (button_count <= NDOF_MAX_BUTTONS_COUNT) ? button_count : NDOF_MAX_BUTTONS_COUNT; in_out_dev->absolute = 0; in_out_dev->valid = 1; in_out_dev->axes_max = 512; @@ -301,6 +312,27 @@ int ndof_libinit(NDOF_DeviceAddCallback in_add_cb, NDOF_DeviceRemovalCallback in_removal_cb, void *platform_specific) { + // Fill the SpaceMouse button mapping table + // + // Remap the buttons with high number codes into the unused spaces + // within the first 32 buttons - likely not how the Windows driver + // does it but at least they will be usable. We also ignore the + // 9th bit. + + for(long i = 0; i < SPACE_MOUSE_BUTTON_SPACE; ++i) + SPACE_MOUSE_BUTTON_MAPPING[i] = i; + + SPACE_MOUSE_BUTTON_MAPPING[282 & 0xff] = 3; /* Rotation lock */ + SPACE_MOUSE_BUTTON_MAPPING[291 & 0xff] = 6; /* Enter */ + SPACE_MOUSE_BUTTON_MAPPING[292 & 0xff] = 7; /* Delete */ + SPACE_MOUSE_BUTTON_MAPPING[430 & 0xff] = 9; /* Tab */ + SPACE_MOUSE_BUTTON_MAPPING[431 & 0xff] = 26; /* Space */ + SPACE_MOUSE_BUTTON_MAPPING[358 & 0xff] = 27; /* V1 */ + SPACE_MOUSE_BUTTON_MAPPING[359 & 0xff] = 28; /* V2 */ + SPACE_MOUSE_BUTTON_MAPPING[360 & 0xff] = 29; /* V3 */ + SPACE_MOUSE_BUTTON_MAPPING[332 & 0xff] = 30; /* 11 */ + SPACE_MOUSE_BUTTON_MAPPING[333 & 0xff] = 31; /* 12 */ + // Initialize the joystick subsystem SDL_InitSubSystem(SDL_INIT_JOYSTICK); @@ -368,8 +400,9 @@ void ndof_update(NDOF_Device *in_dev) switch (ev.type) { case EV_KEY: - // printf("Key %d pressed %d.\n", ev.code, ev.value); - priv->buttons[ev.code & 0xff] = ev.value; + int mapped_code = SPACE_MOUSE_BUTTON_MAPPING[ev.code & 0xff]; + // printf("Key %d (mapped to %d) pressed %d .\n", ev.code, mapped_code, ev.value); + priv->buttons[mapped_code] = ev.value; break; case EV_REL: diff --git a/ndofdev_version.h b/ndofdev_version.h index be09eaf..ea0ad25 100644 --- a/ndofdev_version.h +++ b/ndofdev_version.h @@ -2,6 +2,6 @@ #define NDOFDEF_VERSION_H_ #define NDOFDEV_MAJOR 0 -#define NDOFDEV_MINOR 13 +#define NDOFDEV_MINOR 14 #endif