kopia lustrzana https://github.com/FreeSpacenav/spacenavd
- removed unnecessary devjs handler. Joysticks can be used as regular HID devices
- fixed axis range mapping for various HID devices - fixed device detection which would pick up any logitech device instead of just 3Dconnexion ones git-svn-id: svn+ssh://svn.code.sf.net/p/spacenav/code/trunk/spacenavd@158 ef983eb1-d774-4af8-acfd-baaf7b16a646pull/1/head
rodzic
04aea924e3
commit
42604a51ba
|
@ -28,6 +28,10 @@ tags: $(src) $(hdr)
|
|||
clean:
|
||||
rm -f $(obj) $(bin)
|
||||
|
||||
.PHONY: cleandep
|
||||
cleandep:
|
||||
rm -f $(dep)
|
||||
|
||||
.PHONY: install
|
||||
install: $(bin)
|
||||
$(INSTALL) -d $(DESTDIR)$(PREFIX)/bin
|
||||
|
|
|
@ -94,7 +94,7 @@ int read_cfg(const char *fname, struct cfg *cfg)
|
|||
while(fcntl(fileno(fp), F_SETLKW, &flk) == -1);
|
||||
|
||||
while(fgets(buf, sizeof buf, fp)) {
|
||||
int isint, isfloat, ival, i, bnidx;
|
||||
int isint, isfloat, ival, i, bnidx, axisidx;
|
||||
float fval;
|
||||
char *endp, *key_str, *val_str, *line = buf;
|
||||
while(*line == ' ' || *line == '\t') line++;
|
||||
|
@ -103,11 +103,11 @@ int read_cfg(const char *fname, struct cfg *cfg)
|
|||
continue;
|
||||
}
|
||||
|
||||
if(!(key_str = strtok(line, " :=\n\t\r"))) {
|
||||
if(!(key_str = strtok(line, " =\n\t\r"))) {
|
||||
fprintf(stderr, "invalid config line: %s, skipping.\n", line);
|
||||
continue;
|
||||
}
|
||||
if(!(val_str = strtok(0, " :=\n\t\r"))) {
|
||||
if(!(val_str = strtok(0, " =\n\t\r"))) {
|
||||
fprintf(stderr, "missing value for config key: %s\n", key_str);
|
||||
continue;
|
||||
}
|
||||
|
@ -230,6 +230,18 @@ int read_cfg(const char *fname, struct cfg *cfg)
|
|||
cfg->map_axis[i] = swap_yz ? i : def_axmap[i];
|
||||
}
|
||||
|
||||
} else if(sscanf(key_str, "axismap%d", &axisidx) == 1) {
|
||||
EXPECT(isint);
|
||||
if(axisidx < 0 || axisidx >= MAX_AXES) {
|
||||
fprintf(stderr, "invalid option %s, valid input axis numbers 0 - %d\n", key_str, MAX_AXES - 1);
|
||||
continue;
|
||||
}
|
||||
if(ival < 0 || ival >= 6) {
|
||||
fprintf(stderr, "invalid config value for %s, expected a number from 0 to 6\n", key_str);
|
||||
continue;
|
||||
}
|
||||
cfg->map_axis[axisidx] = ival;
|
||||
|
||||
} else if(sscanf(key_str, "bnmap%d", &bnidx) == 1) {
|
||||
EXPECT(isint);
|
||||
if(bnidx < 0 || bnidx >= MAX_BUTTONS || ival < 0 || ival >= MAX_BUTTONS) {
|
||||
|
|
|
@ -21,14 +21,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
#include <limits.h>
|
||||
|
||||
#define MAX_AXES 64
|
||||
#define MAX_BUTTONS 64
|
||||
#define MAX_CUSTOM 64
|
||||
|
||||
struct cfg {
|
||||
float sensitivity, sens_trans[3], sens_rot[3];
|
||||
int dead_threshold[6];
|
||||
int invert[6];
|
||||
int map_axis[6];
|
||||
int dead_threshold[MAX_AXES];
|
||||
int invert[MAX_AXES];
|
||||
int map_axis[MAX_AXES];
|
||||
int map_button[MAX_BUTTONS];
|
||||
int kbmap[MAX_BUTTONS];
|
||||
char *kbmap_str[MAX_BUTTONS];
|
||||
|
|
23
src/dev.c
23
src/dev.c
|
@ -22,7 +22,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <unistd.h>
|
||||
#include "dev.h"
|
||||
#include "dev_usb.h"
|
||||
#include "dev_js.h"
|
||||
#include "dev_serial.h"
|
||||
#include "event.h" /* remove pending events upon device removal */
|
||||
#include "spnavd.h"
|
||||
|
@ -70,7 +69,7 @@ int init_devices(void)
|
|||
dev = add_device();
|
||||
strcpy(dev->path, usbdev->devfiles[i]);
|
||||
|
||||
if(open_dev_usb(dev) == -1 && open_dev_js(dev) == -1) {
|
||||
if(open_dev_usb(dev) == -1) {
|
||||
remove_device(dev);
|
||||
} else {
|
||||
printf("using device: %s\n", dev->path);
|
||||
|
@ -186,15 +185,33 @@ struct device *get_devices(void)
|
|||
return dev_list;
|
||||
}
|
||||
|
||||
static int devid_list[][2] = {
|
||||
/* 3Dconnexion devices */
|
||||
{0x46d, 0xc621}, /* spaceball 5000 */
|
||||
{0x46d, 0xc625}, /* space pilot */
|
||||
{0x46d, 0xc626}, /* space navigator */
|
||||
|
||||
{-1, -1}
|
||||
};
|
||||
|
||||
static int match_usbdev(const struct usb_device_info *devinfo)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* if it's a 3Dconnexion device match it immediately */
|
||||
if(devinfo->vendorid == 0x046d || (devinfo->name && strstr(devinfo->name, "3Dconnexion"))) {
|
||||
if((devinfo->name && strstr(devinfo->name, "3Dconnexion"))) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* match any device in the devid_list */
|
||||
if(devinfo->vendorid != -1 && devinfo->productid != -1) {
|
||||
for(i=0; devid_list[i][0] > 0; i++) {
|
||||
if(devinfo->vendorid == devid_list[i][0] && devinfo->productid == devid_list[i][1]) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* match any joystick devices listed in the config file */
|
||||
for(i=0; i<MAX_CUSTOM; i++) {
|
||||
if(cfg.devid[i][0] != -1 && cfg.devid[i][1] != -1 &&
|
||||
|
|
|
@ -31,6 +31,10 @@ struct device {
|
|||
char name[MAX_DEV_NAME];
|
||||
char path[PATH_MAX];
|
||||
|
||||
int num_axes;
|
||||
int *minval, *maxval; /* input value range (default: -500, 500) */
|
||||
int *fuzz; /* noise threshold */
|
||||
|
||||
void (*close)(struct device*);
|
||||
int (*read)(struct device*, struct dev_input*);
|
||||
void (*set_led)(struct device*, int);
|
||||
|
|
25
src/dev_js.h
25
src/dev_js.h
|
@ -1,25 +0,0 @@
|
|||
/*
|
||||
spacenavd - a free software replacement driver for 6dof space-mice.
|
||||
Copyright (C) 2007-2013 John Tsiombikas <nuclear@member.fsf.org>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef DEV_JS_H_
|
||||
#define DEV_JS_H_
|
||||
|
||||
#include "dev.h"
|
||||
|
||||
int open_dev_js(struct device *dev);
|
||||
|
||||
#endif /* DEV_JS_H_ */
|
|
@ -1,118 +0,0 @@
|
|||
/*
|
||||
spacenavd - a free software replacement driver for 6dof space-mice.
|
||||
Copyright (C) 2007-2013 John Tsiombikas <nuclear@member.fsf.org>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifdef __linux__
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/joystick.h>
|
||||
#include "event.h"
|
||||
#include "dev.h"
|
||||
#include "dev_js.h"
|
||||
|
||||
#define IS_DEV_OPEN(dev) ((dev)->fd >= 0)
|
||||
|
||||
static void close_jsdev(struct device *dev);
|
||||
static int read_jsdev(struct device *dev, struct dev_input *inp);
|
||||
|
||||
int open_dev_js(struct device *dev)
|
||||
{
|
||||
int naxes = 6;
|
||||
int nbuttons = 0;
|
||||
|
||||
if((dev->fd = open(dev->path, O_RDONLY)) == -1) {
|
||||
fprintf(stderr, "failed to open joystick device: %s: %s\n", dev->path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ioctl(dev->fd, JSIOCGNAME(sizeof dev->name), dev->name) == -1) {
|
||||
perror("JSIOCGNAME failed");
|
||||
strcpy(dev->name, "unknown joystick");
|
||||
}
|
||||
printf("device (joystick) name: %s\n", dev->name);
|
||||
|
||||
if(ioctl(dev->fd, JSIOCGAXES, &naxes) == -1) {
|
||||
perror("failed to get number of axes");
|
||||
}
|
||||
if(ioctl(dev->fd, JSIOCGBUTTONS, &nbuttons) == -1) {
|
||||
perror("failed to get number of buttons");
|
||||
}
|
||||
|
||||
fcntl(dev->fd, F_SETFL, fcntl(dev->fd, F_GETFL) | O_NONBLOCK);
|
||||
|
||||
dev->close = close_jsdev;
|
||||
dev->read = read_jsdev;
|
||||
dev->set_led = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void close_jsdev(struct device *dev)
|
||||
{
|
||||
if(IS_DEV_OPEN(dev)) {
|
||||
close(dev->fd);
|
||||
dev->fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int read_jsdev(struct device *dev, struct dev_input *inp)
|
||||
{
|
||||
struct js_event jev;
|
||||
int rdbytes;
|
||||
|
||||
if(!IS_DEV_OPEN(dev)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
rdbytes = read(dev->fd, &jev, sizeof jev);
|
||||
} while(rdbytes == -1 && errno == EINTR);
|
||||
|
||||
/* disconnect? */
|
||||
if(rdbytes == -1) {
|
||||
if(errno != EAGAIN) {
|
||||
perror("js read error");
|
||||
remove_device(dev);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(rdbytes > 0) {
|
||||
inp->tm.tv_sec = jev.time / 1000;
|
||||
inp->tm.tv_usec = (jev.time % 1000) * 1000;
|
||||
|
||||
if(jev.type & JS_EVENT_AXIS) {
|
||||
inp->type = INP_MOTION;
|
||||
inp->idx = jev.number;
|
||||
inp->val = (float)jev.value / (float)SHRT_MAX;
|
||||
} else if(jev.type & JS_EVENT_BUTTON) {
|
||||
inp->type = INP_BUTTON;
|
||||
inp->idx = jev.number;
|
||||
inp->val = jev.value;
|
||||
} else {
|
||||
fprintf(stderr, "js input: unknown event type (%x)\n", (unsigned int)jev.type);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* __linux__ */
|
|
@ -35,6 +35,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "event.h"
|
||||
#include "hotplug.h"
|
||||
|
||||
#define DEF_MINVAL (-500)
|
||||
#define DEF_MAXVAL 500
|
||||
#define DEF_RANGE (DEF_MAXVAL - DEF_MINVAL)
|
||||
|
||||
#define IS_DEV_OPEN(dev) ((dev)->fd >= 0)
|
||||
|
||||
/* sometimes the rotation events are missing from linux/input.h */
|
||||
|
@ -60,7 +64,9 @@ static void set_led_evdev(struct device *dev, int state);
|
|||
|
||||
int open_dev_usb(struct device *dev)
|
||||
{
|
||||
/*unsigned char evtype_mask[(EV_MAX + 7) / 8];*/
|
||||
int i;
|
||||
struct input_absinfo absinfo;
|
||||
unsigned char evtype_mask[(EV_MAX + 7) / 8];
|
||||
|
||||
if((dev->fd = open(dev->path, O_RDWR)) == -1) {
|
||||
if((dev->fd = open(dev->path, O_RDONLY)) == -1) {
|
||||
|
@ -76,6 +82,51 @@ int open_dev_usb(struct device *dev)
|
|||
}
|
||||
printf("device name: %s\n", dev->name);
|
||||
|
||||
/* get number of axes */
|
||||
dev->num_axes = 6; /* default to regular 6dof controller axis count */
|
||||
if(ioctl(dev->fd, EVIOCGBIT(EV_ABS, sizeof evtype_mask), evtype_mask) == 0) {
|
||||
dev->num_axes = 0;
|
||||
for(i=0; i<ABS_CNT; i++) {
|
||||
int idx = i / 8;
|
||||
int bit = i % 8;
|
||||
|
||||
if(evtype_mask[idx] & (1 << bit)) {
|
||||
dev->num_axes++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(verbose) {
|
||||
printf(" Number of axes: %d\n", dev->num_axes);
|
||||
}
|
||||
|
||||
dev->minval = malloc(dev->num_axes * sizeof *dev->minval);
|
||||
dev->maxval = malloc(dev->num_axes * sizeof *dev->maxval);
|
||||
dev->fuzz = malloc(dev->num_axes * sizeof *dev->fuzz);
|
||||
|
||||
if(!dev->minval || !dev->maxval || !dev->fuzz) {
|
||||
perror("failed to allocate memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if the device is an absolute device, find the minimum and maximum axis values */
|
||||
for(i=0; i<dev->num_axes; i++) {
|
||||
dev->minval[i] = DEF_MINVAL;
|
||||
dev->maxval[i] = DEF_MAXVAL;
|
||||
dev->fuzz[i] = 0;
|
||||
|
||||
if(ioctl(dev->fd, EVIOCGABS(i), &absinfo) == 0) {
|
||||
dev->minval[i] = absinfo.minimum;
|
||||
dev->maxval[i] = absinfo.maximum;
|
||||
dev->fuzz[i] = absinfo.fuzz;
|
||||
|
||||
if(verbose) {
|
||||
printf(" Axis %d value range: %d - %d (fuzz: %d)\n", i, dev->minval[i], dev->maxval[i], dev->fuzz[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*if(ioctl(dev->fd, EVIOCGBIT(0, sizeof(evtype_mask)), evtype_mask) == -1) {
|
||||
perror("EVIOCGBIT ioctl failed\n");
|
||||
close(dev->fd);
|
||||
|
@ -86,7 +137,7 @@ int open_dev_usb(struct device *dev)
|
|||
int grab = 1;
|
||||
/* try to grab the device */
|
||||
if(ioctl(dev->fd, EVIOCGRAB, &grab) == -1) {
|
||||
perror("failed to grab the spacenav device");
|
||||
perror("failed to grab the device");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,6 +165,16 @@ static void close_evdev(struct device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
static INLINE int map_range(struct device *dev, int axidx, int val)
|
||||
{
|
||||
int range = dev->maxval[axidx] - dev->minval[axidx];
|
||||
if(range <= 0) {
|
||||
return val;
|
||||
}
|
||||
|
||||
return (val - dev->minval[axidx]) * DEF_RANGE / range + DEF_MINVAL;
|
||||
}
|
||||
|
||||
static int read_evdev(struct device *dev, struct dev_input *inp)
|
||||
{
|
||||
struct input_event iev; /* linux evdev event */
|
||||
|
@ -143,12 +204,14 @@ static int read_evdev(struct device *dev, struct dev_input *inp)
|
|||
inp->type = INP_MOTION;
|
||||
inp->idx = iev.code - REL_X;
|
||||
inp->val = iev.value;
|
||||
/*printf("[%s] EV_REL(%d): %d\n", dev->name, inp->idx, iev.value);*/
|
||||
break;
|
||||
|
||||
case EV_ABS:
|
||||
inp->type = INP_MOTION;
|
||||
inp->idx = iev.code - ABS_X;
|
||||
inp->val = iev.value;
|
||||
inp->val = map_range(dev, inp->idx, iev.value);
|
||||
/*printf("[%s] EV_ABS(%d): %d (orig: %d)\n", dev->name, inp->idx, inp->val, iev.value);*/
|
||||
break;
|
||||
|
||||
case EV_KEY:
|
||||
|
@ -159,6 +222,7 @@ static int read_evdev(struct device *dev, struct dev_input *inp)
|
|||
|
||||
case EV_SYN:
|
||||
inp->type = INP_FLUSH;
|
||||
/*printf("[%s] EV_SYN\n", dev->name);*/
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
14
src/spnavd.h
14
src/spnavd.h
|
@ -30,6 +30,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#define MAX_DEVICES 8
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus) || (__STDC_VERSION__ >= 199901L)
|
||||
#define INLINE inline
|
||||
#else /* not C++ or C99 */
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define INLINE __inline__
|
||||
#else
|
||||
#define INLINE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
struct cfg cfg;
|
||||
int verbose;
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue