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) {