diff --git a/src/dev.c b/src/dev.c
index 0622736..4a472a3 100644
--- a/src/dev.c
+++ b/src/dev.c
@@ -35,8 +35,6 @@ along with this program. If not, see .
#endif
-#define VENDOR_3DCONNEXION 0x256f
-
/* The device flags are introduced to normalize input across all known
* supported 6dof devices. Newer USB devices seem to use axis 1 as fwd/back and
* axis 2 as up/down, while older serial devices (and possibly also the early
@@ -57,9 +55,6 @@ enum {
* actual buttons when a negative number is passed as argument, and the button
* mapping otherwise.
*/
-int bnhack_smpro(int bn);
-int bnhack_sment(int bn);
-
static struct usbdb_entry {
int usbid[2];
int type;
@@ -76,7 +71,7 @@ static struct usbdb_entry {
{{0x046d, 0xc627}, DEV_SEXP, DF_SWAPYZ | DF_INVYZ, 0}, /* space explorer */
{{0x046d, 0xc628}, DEV_SNAVNB, DF_SWAPYZ | DF_INVYZ, 0}, /* space navigator for notebooks*/
{{0x046d, 0xc629}, DEV_SPILOTPRO, DF_SWAPYZ | DF_INVYZ, 0}, /* space pilot pro*/
- {{0x046d, 0xc62b}, DEV_SMPRO, DF_SWAPYZ | DF_INVYZ, 0}, /* space mouse pro*/
+ {{0x046d, 0xc62b}, DEV_SMPRO, DF_SWAPYZ | DF_INVYZ, bnhack_smpro}, /* space mouse pro*/
{{0x046d, 0xc640}, DEV_NULOOQ, 0, 0}, /* nulooq */
{{0x256f, 0xc62e}, DEV_SMW, DF_SWAPYZ | DF_INVYZ, 0}, /* spacemouse wireless (USB cable) */
{{0x256f, 0xc62f}, DEV_SMW, DF_SWAPYZ | DF_INVYZ, 0}, /* spacemouse wireless receiver */
@@ -191,7 +186,7 @@ int init_devices_usb(void)
remove_device(dev);
} else {
/* add the 6dof remapping flags to every future 3dconnexion device */
- if(dev->usbid[0] == VENDOR_3DCONNEXION) {
+ if(dev->usbid[0] == VID_3DCONN) {
dev->flags |= DF_SWAPYZ | DF_INVYZ;
}
/* sanity-check the device flags */
@@ -395,7 +390,7 @@ static int match_usbdev(const struct usb_dev_info *devinfo)
}
/* match any device with the new 3Dconnexion device id */
- if(vid == VENDOR_3DCONNEXION) {
+ if(vid == VID_3DCONN) {
/* avoid matching and trying to grab the CAD mouse, when connected
* on the same universal receiver as the spacemouse.
*/
diff --git a/src/dev_usb.h b/src/dev_usb.h
index 2abec32..e5b6a3e 100644
--- a/src/dev_usb.h
+++ b/src/dev_usb.h
@@ -18,6 +18,9 @@ along with this program. If not, see .
#ifndef SPNAV_DEV_USB_H_
#define SPNAV_DEV_USB_H_
+#define VID_3DCONN 0x256f
+#define PID_WIRELESS 0xc652
+
struct device;
int open_dev_usb(struct device *dev);
@@ -37,4 +40,8 @@ struct usb_dev_info *find_usb_devices(int (*match)(const struct usb_dev_info*));
void free_usb_devices_list(struct usb_dev_info *list);
void print_usb_device_info(struct usb_dev_info *devinfo);
+/* see usbdb_entry table bnmap field in dev.c */
+int bnhack_smpro(int bn);
+int bnhack_sment(int bn);
+
#endif /* SPNAV_DEV_USB_H_ */
diff --git a/src/dev_usb_linux.c b/src/dev_usb_linux.c
index d2d07e8..e965395 100644
--- a/src/dev_usb_linux.c
+++ b/src/dev_usb_linux.c
@@ -109,6 +109,15 @@ int open_dev_usb(struct device *dev)
}
dev->num_axes = axes_rel + axes_abs;
if(!dev->num_axes) {
+ if(dev->usbid[0] == VID_3DCONN && dev->usbid[1] == PID_WIRELESS) {
+ /* a wireless 3Dconnexion device without axes is probably one of the
+ * CadMouse products, drop it.
+ */
+ logmsg(LOG_DEBUG, "No axes detected, probably a CadMouse, dropping\n");
+ close(dev->fd);
+ dev->fd = -1;
+ return -1;
+ }
logmsg(LOG_WARNING, "failed to retrieve number of axes. assuming 6\n");
dev->num_axes = 6;
} else {
@@ -118,25 +127,49 @@ int open_dev_usb(struct device *dev)
}
/* get number of buttons */
+ dev->num_buttons = 0;
+ if(ioctl(dev->fd, EVIOCGBIT(EV_KEY, sizeof evtype_mask), evtype_mask) != -1) {
+ for(i=0; inum_buttons++;
+ }
+ }
+ } else {
+ logmsg(LOG_DEBUG, "EVIOCGBIT(EV_KEY) ioctl failed: %s\n", strerror(errno));
+ }
+
+ /* sanity check, problematic devices appear to report 256 buttons, if that's
+ * not the case, this is probably a mistake.
+ */
+ if(dev->bnhack && dev->num_buttons < 255) {
+ logmsg(LOG_DEBUG, "BUG! Please report this at https://github.com/FreeSpacenav/spacenavd/issues, "
+ "or by sending an email to nuclear@member.fsf.org.\n");
+ logmsg(LOG_DEBUG, "This device (%04x:%04x) was marked for disjointed "
+ "button remapping, but unexpectedly reports %d buttons\n",
+ dev->usbid[0], dev->usbid[1], dev->num_buttons);
+
+ dev->bnhack = 0;
+ }
+
if(dev->bnhack) {
- /* for those problematic devices, rely on the hardcoded button value in
- * their button remapping hack
- */
dev->num_buttons = dev->bnhack(-1);
} else {
- dev->num_buttons = 0;
- if(ioctl(dev->fd, EVIOCGBIT(EV_KEY, sizeof evtype_mask), evtype_mask) != -1) {
- for(i=0; inum_buttons++;
- }
+ if(dev->usbid[0] == VID_3DCONN && dev->usbid[1] == PID_WIRELESS) {
+ /* Wireless devices use the same dongle, try to guess which actual
+ * device this is, and apply the button hack if it's a SpcMouse Pro
+ */
+ if(dev->num_buttons >= 255) {
+ dev->type = DEV_SMPROW;
+ dev->bnhack = bnhack_smpro;
+ dev->num_buttons = bnhack_smpro(-1);
+ strcpy(dev->name, "3Dconnexion SpaceMouse Pro Wireless (guess)");
+ } else {
+ dev->type = DEV_SMW;
+ strcpy(dev->name, "3Dconnexion SpaceMouse Wireless (guess)");
}
- } else {
- logmsg(LOG_DEBUG, "EVIOCGBIT(EV_KEY) ioctl failed: %s\n", strerror(errno));
}
}
if(!dev->num_buttons) {