fixed protocol v1 handling bugs

pull/67/head
John Tsiombikas 2022-02-12 16:47:09 +02:00
rodzic 7145788c5e
commit 62cb5389c4
4 zmienionych plików z 104 dodań i 75 usunięć

Wyświetl plik

@ -48,7 +48,7 @@ struct client *add_client(int type, void *cdata)
return 0;
}
if(!(client = malloc(sizeof *client))) {
if(!(client = calloc(1, sizeof *client))) {
return 0;
}

Wyświetl plik

@ -1,6 +1,6 @@
/*
spacenavd - a free software replacement driver for 6dof space-mice.
Copyright (C) 2007-2010 John Tsiombikas <nuclear@member.fsf.org>
Copyright (C) 2007-2022 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
@ -45,6 +45,9 @@ struct client {
float sens; /* sensitivity */
struct device *dev;
char reqbuf[64];
int reqbytes;
struct client *next;
};

65
src/proto.h 100644
Wyświetl plik

@ -0,0 +1,65 @@
/*
spacenavd - a free software replacement driver for 6dof space-mice.
Copyright (C) 2007-2022 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 PROTO_H_
#define PROTO_H_
/* maximum supported protocol version */
#define MAX_PROTO_VER 1
struct reqresp {
int type;
int data[7];
};
#define REQ_TAG 0x7faa0000
#define REQ_BASE 0x1000
/* REQ_S* are set, REQ_G* are get requests.
* Quick-reference for request-response data in the comments next to each
* request: Q[n] defines request data item n, R[n] defines response data item n
*
* status responses are 0 for success, non-zero for failure
*/
enum {
/* per-client settings */
REQ_SET_SENS = REQ_BASE,/* set client sensitivity: Q[0] float - R[6] status */
REQ_GET_SENS, /* get client sensitivity: R[0] float R[6] status */
/* device queries */
REQ_DEV_NAME = 0x2000, /* get device name: R[0] length R[6] status followed
by <length> bytes */
REQ_DEV_PATH, /* get device path: same as above */
REQ_DEV_NAXES, /* get number of axes: R[0] num axes R[6] status */
REQ_DEV_NBUTTONS, /* get number of buttons: same as above */
/* TODO: features like LCD, LEDs ... */
/* configuration settings */
REQ_SCFG_SENS = 0x3000, /* set global sensitivity: Q[0] float - R[6] status */
REQ_GCFG_SENS, /* get global sens: R[0] float R[6] status */
REQ_SCFG_SENS_AXIS, /* set per-axis sens/ty: Q[0-5] values - R[6] status */
REQ_GCFG_SENS_AXIS, /* get per-axis sens/ty: R[0-5] values R[6] status */
REQ_SCFG_DEADZONE, /* set deadzones: Q[0-5] values - R[6] status */
REQ_GCFG_DEADZONE, /* get deadzones: R[0-5] values R[6] status */
REQ_SCFG_INVERT, /* set invert axes: Q[0-5] invert - R[6] status */
REQ_GCFG_INVERT, /* get invert axes: R[0-5] invert R[6] status */
/* TODO ... more */
REQ_CHANGE_PROTO = 0x5500
};
#endif /* PROTO_H_ */

Wyświetl plik

@ -27,49 +27,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include "proto.h"
#include "proto_unix.h"
#include "spnavd.h"
/* maximum supported protocol version */
#define MAX_PROTO_VER 1
struct reqresp {
int type;
int data[7];
};
/* REQ_S* are set, REQ_G* are get requests.
* Quick-reference for request-response data in the comments next to each
* request: Q[n] defines request data item n, R[n] defines response data item n
*
* status responses are 0 for success, non-zero for failure
*/
enum {
/* per-client settings */
REQ_SET_SENS, /* set client sensitivity: Q[0] float - R[6] status */
REQ_GET_SENS, /* get client sensitivity: R[0] float R[6] status */
/* device queries */
REQ_DEV_NAME = 0x1000, /* get device name: R[0] length R[6] status followed
by <length> bytes */
REQ_DEV_PATH, /* get device path: same as above */
REQ_DEV_NAXES, /* get number of axes: R[0] num axes R[6] status */
REQ_DEV_NBUTTONS, /* get number of buttons: same as above */
/* TODO: features like LCD, LEDs ... */
/* configuration settings */
REQ_SCFG_SENS = 0x2000, /* set global sensitivity: Q[0] float - R[6] status */
REQ_GCFG_SENS, /* get global sens: R[0] float R[6] status */
REQ_SCFG_SENS_AXIS, /* set per-axis sens/ty: Q[0-5] values - R[6] status */
REQ_GCFG_SENS_AXIS, /* get per-axis sens/ty: R[0-5] values R[6] status */
REQ_SCFG_DEADZONE, /* set deadzones: Q[0-5] values - R[6] status */
REQ_GCFG_DEADZONE, /* get deadzones: R[0-5] values R[6] status */
REQ_SCFG_INVERT, /* set invert axes: Q[0-5] invert - R[6] status */
REQ_GCFG_INVERT, /* get invert axes: R[0-5] invert R[6] status */
/* TODO ... more */
REQ_CHANGE_PROTO = 0x7faa5500
};
enum {
UEV_TYPE_MOTION,
@ -172,8 +133,6 @@ void send_uevent(spnav_event *ev, struct client *c)
int handle_uevents(fd_set *rset)
{
struct client *citer;
static char reqbuf[64];
static int reqbytes;
struct reqresp *req;
if(lsock == -1) {
@ -210,34 +169,31 @@ int handle_uevents(fd_set *rset)
float sens;
/* handle client requests */
while((rdbytes = read(s, &msg, sizeof msg)) <= 0 && errno == EINTR);
if(rdbytes <= 0) { /* something went wrong... disconnect client */
close(get_client_socket(c));
remove_client(c);
continue;
}
/* only handle magic NaN protocol change requests, when the
* client is operating in protocol 0 mode
*/
if(c->proto == 0 && (msg & 0xffffff00) == REQ_CHANGE_PROTO) {
c->proto = msg & 0xff;
/* if the client requests a protocol version higher than the
* daemon supports, return the maximum supported version and
* switch to that.
*/
if(c->proto > MAX_PROTO_VER) {
c->proto = MAX_PROTO_VER;
msg = REQ_CHANGE_PROTO | MAX_PROTO_VER;
write(s, &msg, sizeof msg);
}
continue;
}
switch(c->proto) {
case 0:
while((rdbytes = read(s, &msg, sizeof msg)) <= 0 && errno == EINTR);
if(rdbytes <= 0) { /* something went wrong... disconnect client */
close(get_client_socket(c));
remove_client(c);
continue;
}
/* handle magic NaN protocol change requests */
if((msg & 0xffffff00) == (REQ_TAG | REQ_CHANGE_PROTO)) {
c->proto = msg & 0xff;
/* if the client requests a protocol version higher than the
* daemon supports, return the maximum supported version and
* switch to that.
*/
if(c->proto > MAX_PROTO_VER) {
c->proto = MAX_PROTO_VER;
msg = REQ_TAG | REQ_CHANGE_PROTO | MAX_PROTO_VER;
}
write(s, &msg, sizeof msg);
continue;
}
/* protocol v0: only sensitivity comes from clients */
sens = *(float*)&msg;
if(isfinite(sens)) {
@ -247,10 +203,15 @@ int handle_uevents(fd_set *rset)
case 1:
/* protocol v1: accumulate request bytes, and process */
reqbytes += read(s, reqbuf + reqbytes, sizeof *req - reqbytes);
if(reqbytes >= sizeof *req) {
reqbytes = 0;
req = (struct reqresp*)reqbuf;
c->reqbytes += read(s, c->reqbuf + c->reqbytes, sizeof *req - c->reqbytes);
if(c->reqbytes >= sizeof *req) {
req = (struct reqresp*)c->reqbuf;
/*
logmsg(LOG_INFO, "DBG REQ (%d): %x - %x %x %x %x %x %x %x\n", c->reqbytes,
req->type, req->data[0], req->data[1], req->data[2],
req->data[3], req->data[4], req->data[5], req->data[6]);
*/
c->reqbytes = 0;
if(handle_request(c, req) == -1) {
close(s);
remove_client(c);
@ -277,7 +238,7 @@ static int handle_request(struct client *c, struct reqresp *req)
float fval, fvec[6];
struct device *dev;
switch(req->type) {
switch(req->type & 0xffff) {
case REQ_SET_SENS:
fval = *(float*)req->data;
if(isfinite(fval)) {