kopia lustrzana https://github.com/FreeSpacenav/spacenavd
preparing for the smarter config file writer
rodzic
8f062901b0
commit
3cfc60b80e
152
src/cfgfile.c
152
src/cfgfile.c
|
|
@ -21,11 +21,30 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include "cfgfile.h"
|
||||
#include "logger.h"
|
||||
#include "spnavd.h"
|
||||
|
||||
/* all parsable config options... some of them might map to the same cfg field */
|
||||
enum {
|
||||
CFG_REPEAT,
|
||||
CFG_DEADZONE,
|
||||
CFG_DEADZONE_TX, CFG_DEADZONE_TY, CFG_DEADZONE_TZ,
|
||||
CFG_DEADZONE_RX, CFG_DEADZONE_RY, CFG_DEADZONE_RZ,
|
||||
CFG_SENS,
|
||||
CFG_SENS_TRANS, CFG_SENS_TX, CFG_SENS_TY, CFG_SENS_TZ,
|
||||
CFG_SENS_ROT, CFG_SENS_RX, CFG_SENS_RY, CFG_SENS_RZ,
|
||||
CFG_INVROT, CFG_INVTRANS, CFG_SWAPYZ,
|
||||
CFG_AXISMAP_N, CFG_BNMAP_N, CFG_BNACT_N, CFG_KBMAP_N,
|
||||
CFG_LED, CFG_GRAB,
|
||||
CFG_SERIAL, CFG_DEVID,
|
||||
|
||||
NUM_CFG_OPTIONS
|
||||
};
|
||||
|
||||
static int parse_bnact(const char *s);
|
||||
|
||||
enum {TX, TY, TZ, RX, RY, RZ};
|
||||
|
|
@ -33,6 +52,17 @@ enum {TX, TY, TZ, RX, RY, RZ};
|
|||
static const int def_axmap[] = {0, 2, 1, 3, 5, 4};
|
||||
static const int def_axinv[] = {0, 1, 1, 0, 1, 1};
|
||||
|
||||
struct cfgline {
|
||||
char *str; /* points where in the cfgbuf this line starts at */
|
||||
int opt; /* CFG_* item */
|
||||
int idx;
|
||||
};
|
||||
|
||||
static char *cfgbuf;
|
||||
static struct cfgline *cfglines;
|
||||
static int num_lines;
|
||||
|
||||
|
||||
void default_cfg(struct cfg *cfg)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -70,6 +100,15 @@ void default_cfg(struct cfg *cfg)
|
|||
}
|
||||
}
|
||||
|
||||
void unlock_cfgfile(int fd)
|
||||
{
|
||||
struct flock flk;
|
||||
flk.l_type = F_UNLCK;
|
||||
flk.l_start = flk.l_len = 0;
|
||||
flk.l_whence = SEEK_SET;
|
||||
fcntl(fd, F_SETLK, &flk);
|
||||
}
|
||||
|
||||
#define EXPECT(cond) \
|
||||
do { \
|
||||
if(!(cond)) { \
|
||||
|
|
@ -80,16 +119,17 @@ void default_cfg(struct cfg *cfg)
|
|||
|
||||
int read_cfg(const char *fname, struct cfg *cfg)
|
||||
{
|
||||
FILE *fp;
|
||||
char buf[512];
|
||||
int i, j, fd;
|
||||
char buf[512], *ptr;
|
||||
struct flock flk;
|
||||
int num_devid = 0;
|
||||
/*int num_devnames = 0;*/
|
||||
struct stat st;
|
||||
|
||||
default_cfg(cfg);
|
||||
|
||||
logmsg(LOG_INFO, "reading config file: %s\n", fname);
|
||||
if(!(fp = fopen(fname, "r"))) {
|
||||
if((fd = open(fname, O_RDONLY)) == -1) {
|
||||
logmsg(LOG_WARNING, "failed to open config file %s: %s. using defaults.\n", fname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -98,12 +138,63 @@ int read_cfg(const char *fname, struct cfg *cfg)
|
|||
flk.l_type = F_RDLCK;
|
||||
flk.l_start = flk.l_len = 0;
|
||||
flk.l_whence = SEEK_SET;
|
||||
while(fcntl(fileno(fp), F_SETLKW, &flk) == -1);
|
||||
while(fcntl(fd, F_SETLKW, &flk) == -1);
|
||||
|
||||
while(fgets(buf, sizeof buf, fp)) {
|
||||
int isint, isfloat, ival, i, bnidx, axisidx;
|
||||
/* read the file into cfgbuf */
|
||||
fstat(fd, &st);
|
||||
free(cfgbuf);
|
||||
cfgbuf = 0;
|
||||
if(!st.st_size || !(cfgbuf = malloc(st.st_size + 1))) {
|
||||
logmsg(LOG_WARNING, "failed to allocate config file %s buffer (%ld bytes). using defaults.\n", fname, (long)st.st_size);
|
||||
unlock_cfgfile(fd);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
if(read(fd, cfgbuf, st.st_size) < st.st_size) {
|
||||
logmsg(LOG_WARNING, "failed to read config file %s: %s. using defaults.\n", fname, strerror(errno));
|
||||
free(cfgbuf);
|
||||
cfgbuf = 0;
|
||||
unlock_cfgfile(fd);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
cfgbuf[st.st_size] = 0;
|
||||
unlock_cfgfile(fd);
|
||||
close(fd);
|
||||
|
||||
/* count newlines and populate lines array */
|
||||
num_lines = 0;
|
||||
ptr = cfgbuf;
|
||||
for(i=0; i<st.st_size; i++) {
|
||||
if(*ptr++ == '\n') num_lines++;
|
||||
}
|
||||
if(!num_lines) num_lines = 1;
|
||||
|
||||
if(!(cfglines = calloc(num_lines, sizeof *cfglines))) {
|
||||
logmsg(LOG_WARNING, "failed to allocate config lines buffer (%d lines)\n", num_lines);
|
||||
free(cfgbuf);
|
||||
cfgbuf = 0;
|
||||
}
|
||||
num_lines = 0;
|
||||
cfglines[num_lines++].str = cfgbuf;
|
||||
ptr = cfgbuf;
|
||||
for(i=0; i<st.st_size; i++) {
|
||||
if(*ptr == '\n') {
|
||||
*ptr = 0;
|
||||
cfglines[num_lines++].str = ptr + 1;
|
||||
}
|
||||
++ptr;
|
||||
}
|
||||
|
||||
/* parse config file */
|
||||
for(i=0; i<num_lines; i++) {
|
||||
int isint, isfloat, ival, bnidx, axisidx;
|
||||
float fval;
|
||||
char *endp, *key_str, *val_str, *line = buf;
|
||||
|
||||
strncpy(buf, cfglines[i].str, sizeof buf - 1);
|
||||
buf[sizeof buf - 1] = 0;
|
||||
|
||||
while(*line == ' ' || *line == '\t') line++;
|
||||
|
||||
if(!*line || *line == '\n' || *line == '\r' || *line == '#') {
|
||||
|
|
@ -126,76 +217,94 @@ int read_cfg(const char *fname, struct cfg *cfg)
|
|||
isfloat = (endp > val_str);
|
||||
|
||||
if(strcmp(key_str, "repeat-interval") == 0) {
|
||||
cfglines[i].opt = CFG_REPEAT;
|
||||
EXPECT(isint);
|
||||
cfg->repeat_msec = ival;
|
||||
|
||||
} else if(strcmp(key_str, "dead-zone") == 0) {
|
||||
cfglines[i].opt = CFG_DEADZONE;
|
||||
EXPECT(isint);
|
||||
for(i=0; i<6; i++) {
|
||||
cfg->dead_threshold[i] = ival;
|
||||
for(j=0; j<6; j++) {
|
||||
cfg->dead_threshold[j] = ival;
|
||||
}
|
||||
|
||||
} else if(strcmp(key_str, "dead-zone-translation-x") == 0) {
|
||||
cfglines[i].opt = CFG_DEADZONE_TX;
|
||||
EXPECT(isint);
|
||||
cfg->dead_threshold[0] = ival;
|
||||
|
||||
} else if(strcmp(key_str, "dead-zone-translation-y") == 0) {
|
||||
cfglines[i].opt = CFG_DEADZONE_TY;
|
||||
EXPECT(isint);
|
||||
cfg->dead_threshold[1] = ival;
|
||||
|
||||
} else if(strcmp(key_str, "dead-zone-translation-z") == 0) {
|
||||
cfglines[i].opt = CFG_DEADZONE_TZ;
|
||||
EXPECT(isint);
|
||||
cfg->dead_threshold[2] = ival;
|
||||
|
||||
} else if(strcmp(key_str, "dead-zone-rotation-x") == 0) {
|
||||
cfglines[i].opt = CFG_DEADZONE_RX;
|
||||
EXPECT(isint);
|
||||
cfg->dead_threshold[3] = ival;
|
||||
|
||||
} else if(strcmp(key_str, "dead-zone-rotation-y") == 0) {
|
||||
cfglines[i].opt = CFG_DEADZONE_RY;
|
||||
EXPECT(isint);
|
||||
cfg->dead_threshold[4] = ival;
|
||||
|
||||
} else if(strcmp(key_str, "dead-zone-rotation-z") == 0) {
|
||||
cfglines[i].opt = CFG_DEADZONE_RZ;
|
||||
EXPECT(isint);
|
||||
cfg->dead_threshold[5] = ival;
|
||||
|
||||
} else if(strcmp(key_str, "sensitivity") == 0) {
|
||||
cfglines[i].opt = CFG_SENS;
|
||||
EXPECT(isfloat);
|
||||
cfg->sensitivity = fval;
|
||||
|
||||
} else if(strcmp(key_str, "sensitivity-translation") == 0) {
|
||||
cfglines[i].opt = CFG_SENS_TRANS;
|
||||
EXPECT(isfloat);
|
||||
cfg->sens_trans[0] = cfg->sens_trans[1] = cfg->sens_trans[2] = fval;
|
||||
|
||||
} else if(strcmp(key_str, "sensitivity-translation-x") == 0) {
|
||||
cfglines[i].opt = CFG_SENS_TX;
|
||||
EXPECT(isfloat);
|
||||
cfg->sens_trans[0] = fval;
|
||||
|
||||
} else if(strcmp(key_str, "sensitivity-translation-y") == 0) {
|
||||
cfglines[i].opt = CFG_SENS_TY;
|
||||
EXPECT(isfloat);
|
||||
cfg->sens_trans[1] = fval;
|
||||
|
||||
} else if(strcmp(key_str, "sensitivity-translation-z") == 0) {
|
||||
cfglines[i].opt = CFG_SENS_TZ;
|
||||
EXPECT(isfloat);
|
||||
cfg->sens_trans[2] = fval;
|
||||
|
||||
} else if(strcmp(key_str, "sensitivity-rotation") == 0) {
|
||||
cfglines[i].opt = CFG_SENS_ROT;
|
||||
EXPECT(isfloat);
|
||||
cfg->sens_rot[0] = cfg->sens_rot[1] = cfg->sens_rot[2] = fval;
|
||||
|
||||
} else if(strcmp(key_str, "sensitivity-rotation-x") == 0) {
|
||||
cfglines[i].opt = CFG_SENS_RX;
|
||||
EXPECT(isfloat);
|
||||
cfg->sens_rot[0] = fval;
|
||||
|
||||
} else if(strcmp(key_str, "sensitivity-rotation-y") == 0) {
|
||||
cfglines[i].opt = CFG_SENS_RY;
|
||||
EXPECT(isfloat);
|
||||
cfg->sens_rot[1] = fval;
|
||||
|
||||
} else if(strcmp(key_str, "sensitivity-rotation-z") == 0) {
|
||||
cfglines[i].opt = CFG_SENS_RZ;
|
||||
EXPECT(isfloat);
|
||||
cfg->sens_rot[2] = fval;
|
||||
|
||||
} else if(strcmp(key_str, "invert-rot") == 0) {
|
||||
cfglines[i].opt = CFG_INVROT;
|
||||
if(strchr(val_str, 'x')) {
|
||||
cfg->invert[RX] = !def_axinv[RX];
|
||||
}
|
||||
|
|
@ -207,6 +316,7 @@ int read_cfg(const char *fname, struct cfg *cfg)
|
|||
}
|
||||
|
||||
} else if(strcmp(key_str, "invert-trans") == 0) {
|
||||
cfglines[i].opt = CFG_INVTRANS;
|
||||
if(strchr(val_str, 'x')) {
|
||||
cfg->invert[TX] = !def_axinv[TX];
|
||||
}
|
||||
|
|
@ -218,8 +328,9 @@ int read_cfg(const char *fname, struct cfg *cfg)
|
|||
}
|
||||
|
||||
} else if(strcmp(key_str, "swap-yz") == 0) {
|
||||
int i, swap_yz = 0;
|
||||
int swap_yz = 0;
|
||||
|
||||
cfglines[i].opt = CFG_SWAPYZ;
|
||||
if(isint) {
|
||||
swap_yz = ival;
|
||||
} else {
|
||||
|
|
@ -233,8 +344,8 @@ int read_cfg(const char *fname, struct cfg *cfg)
|
|||
}
|
||||
}
|
||||
|
||||
for(i=0; i<6; i++) {
|
||||
cfg->map_axis[i] = swap_yz ? i : def_axmap[i];
|
||||
for(j=0; j<6; j++) {
|
||||
cfg->map_axis[j] = swap_yz ? i : def_axmap[j];
|
||||
}
|
||||
|
||||
} else if(sscanf(key_str, "axismap%d", &axisidx) == 1) {
|
||||
|
|
@ -247,6 +358,8 @@ int read_cfg(const char *fname, struct cfg *cfg)
|
|||
logmsg(LOG_WARNING, "invalid config value for %s, expected a number from 0 to 6\n", key_str);
|
||||
continue;
|
||||
}
|
||||
cfglines[i].opt = CFG_AXISMAP_N;
|
||||
cfglines[i].idx = axisidx;
|
||||
cfg->map_axis[axisidx] = ival;
|
||||
|
||||
} else if(sscanf(key_str, "bnmap%d", &bnidx) == 1) {
|
||||
|
|
@ -258,6 +371,8 @@ int read_cfg(const char *fname, struct cfg *cfg)
|
|||
if(cfg->map_button[bnidx] != bnidx) {
|
||||
logmsg(LOG_WARNING, "warning: multiple mappings for button %d\n", bnidx);
|
||||
}
|
||||
cfglines[i].opt = CFG_BNMAP_N;
|
||||
cfglines[i].idx = bnidx;
|
||||
cfg->map_button[bnidx] = ival;
|
||||
|
||||
} else if(sscanf(key_str, "bnact%d", &bnidx) == 1) {
|
||||
|
|
@ -265,6 +380,8 @@ int read_cfg(const char *fname, struct cfg *cfg)
|
|||
logmsg(LOG_WARNING, "invalid configuration value for %s, expected a number from 0 to %d\n", key_str, MAX_BUTTONS);
|
||||
continue;
|
||||
}
|
||||
cfglines[i].opt = CFG_BNACT_N;
|
||||
cfglines[i].idx = bnidx;
|
||||
if((cfg->bnact[bnidx] = parse_bnact(val_str)) == -1) {
|
||||
cfg->bnact[bnidx] = BNACT_NONE;
|
||||
logmsg(LOG_WARNING, "invalid button action: \"%s\"\n", val_str);
|
||||
|
|
@ -276,6 +393,8 @@ int read_cfg(const char *fname, struct cfg *cfg)
|
|||
logmsg(LOG_WARNING, "invalid configuration value for %s, expected a number from 0 to %d\n", key_str, MAX_BUTTONS);
|
||||
continue;
|
||||
}
|
||||
cfglines[i].opt = CFG_KBMAP_N;
|
||||
cfglines[i].idx = bnidx;
|
||||
if(cfg->kbmap_str[bnidx]) {
|
||||
logmsg(LOG_WARNING, "warning: multiple keyboard mappings for button %d: %s -> %s\n", bnidx, cfg->kbmap_str[bnidx], val_str);
|
||||
free(cfg->kbmap_str[bnidx]);
|
||||
|
|
@ -283,6 +402,7 @@ int read_cfg(const char *fname, struct cfg *cfg)
|
|||
cfg->kbmap_str[bnidx] = strdup(val_str);
|
||||
|
||||
} else if(strcmp(key_str, "led") == 0) {
|
||||
cfglines[i].opt = CFG_LED;
|
||||
if(isint) {
|
||||
cfg->led = ival;
|
||||
} else {
|
||||
|
|
@ -299,6 +419,7 @@ int read_cfg(const char *fname, struct cfg *cfg)
|
|||
}
|
||||
|
||||
} else if(strcmp(key_str, "grab") == 0) {
|
||||
cfglines[i].opt = CFG_GRAB;
|
||||
if(isint) {
|
||||
cfg->grab_device = ival;
|
||||
} else {
|
||||
|
|
@ -313,10 +434,12 @@ int read_cfg(const char *fname, struct cfg *cfg)
|
|||
}
|
||||
|
||||
} else if(strcmp(key_str, "serial") == 0) {
|
||||
cfglines[i].opt = CFG_SERIAL;
|
||||
strncpy(cfg->serial_dev, val_str, PATH_MAX - 1);
|
||||
|
||||
} else if(strcmp(key_str, "device-id") == 0) {
|
||||
unsigned int vendor, prod;
|
||||
cfglines[i].opt = CFG_DEVID;
|
||||
if(sscanf(val_str, "%x:%x", &vendor, &prod) == 2) {
|
||||
cfg->devid[num_devid][0] = (int)vendor;
|
||||
cfg->devid[num_devid][1] = (int)prod;
|
||||
|
|
@ -331,13 +454,6 @@ int read_cfg(const char *fname, struct cfg *cfg)
|
|||
}
|
||||
}
|
||||
|
||||
/* unlock */
|
||||
flk.l_type = F_UNLCK;
|
||||
flk.l_start = flk.l_len = 0;
|
||||
flk.l_whence = SEEK_SET;
|
||||
fcntl(fileno(fp), F_SETLK, &flk);
|
||||
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue