Wireless device detection, and CadMouse avoidance logic

New 3dconnexion devices seem to all use the same dongle with USB id
256f:c526. That includes at least the SpaceMouse Wireless and the
CadMouse Wireless. This is a set of hacks to guess what's connected
and act accordingly:

  - Drop the CadMouse (num_axes == 0)
  - Enable the button hack if it's a SpaceMouse Pro Wireless
  - Detect SpaceMouse Wirless and update name/type.

Also added a test for the assumption that devices marked for button
remapping always report 255-256 buttons. If that's not the case undo the
button-hack and ask the user to report it as a bug.
pull/65/head
John Tsiombikas 2022-08-26 16:39:26 +03:00
rodzic 21d90d0db6
commit 3e1cbc52ef
3 zmienionych plików z 58 dodań i 23 usunięć

Wyświetl plik

@ -35,8 +35,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#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.
*/

Wyświetl plik

@ -18,6 +18,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#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_ */

Wyświetl plik

@ -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; i<KEY_CNT; i++) {
int idx = i / 8;
int bit = i % 8;
if(evtype_mask[idx] & (1 << bit)) {
dev->num_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; i<KEY_CNT; i++) {
int idx = i / 8;
int bit = i % 8;
if(evtype_mask[idx] & (1 << bit)) {
logmsg(LOG_DEBUG, "bit %d (part %d bit %d)\n", idx * 8 + i, idx, bit);
dev->num_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) {