FreeSpacenav / spacenavd

Free user-space driver for 6-dof space-mice.
http://spacenav.sourceforge.net
GNU General Public License v3.0
279 stars 55 forks source link

Differentiate multiple devices #13

Open tomlankhorst opened 5 years ago

tomlankhorst commented 5 years ago

Is there in the current implementation a way to distinguish input from two or more devices? On first sight, there seems to be no facility in the event structures of libspnav nor in the raw data from the UNIX sockets that differentiates an event produced by device A or B.

Is there a way to achieve this differentiation?

jtsiomb commented 5 years ago

No, there isn't. I've heard this request a couple of times over the years though, so I'll keep it in mind for the upcoming protocol re-design that I wanted to do for some time now. Leaving this open as a feature request.

tomlankhorst commented 5 years ago

Okay, I might submit a (quick) PR these days to realize this for the current protocol.

ggoretkin-bdai commented 10 months ago

I'm wondering if, instead of changing the protocol, spacenavd could just open a new socket per additional device, using the same protocol per socket. libspnav already has functionality to configure the socket path to use.

It's not ideal from the perspective of hotplugging, but it might be a quicker fix.

jtsiomb commented 10 months ago

That might indeed be a quick and easy way to support multiple devices. It would need some refactoring of how devices are handled internally, but would require no protocol changes. And libspnav could hide most of the details from user apps, making it possibly as simple as setting a global flag about multi-device input before opening the connection, and handling events slightly differently to take device id into account...

ggoretkin-bdai commented 10 months ago

Digging in a bit more, it looks like the functionality in https://github.com/FreeSpacenav/spacenavd/commit/7145788c5e1c0c381aec791e157dab6b6a4144ab lays a lot of the groundwork for using the existing single-socket approach. If the request protocol (from client to spacenavd) is expanded so that set_client_device can be called, then each client can listen to a specific device. That approach requires some protocol changes, but they should be backwards compatible, requiring an addition to

enum {
    /* per-client settings */
    REQ_SET_NAME = REQ_BASE,/* set client name: Q[0-5] next 24 bytes Q[6] remaining length - R[6] status */
    REQ_SET_SENS,           /* set client sensitivity:  Q[0] float - R[6] status */
    REQ_GET_SENS,           /* get client sensitivity:  R[0] float R[6] status */
    REQ_SET_EVMASK,         /* set event mask: Q[0] mask - R[6] status */
    REQ_GET_EVMASK,         /* get event mask: R[0] mask R[6] status */
jtsiomb commented 10 months ago

If we're adding things to the protocol, I think binding a device to each client (and having the client open multiple connections) feels ackward.

I think I'd rather co-opt, on request by the application to enable multi-device mode, the extremely useless last field of motion events, for sending a device id. So far it was used to transmit a period between events, which nobody ever uses for anything, and I added initially just because the 3dconnexion X11 protocol had it.

The "activate multi-device mode" request can return the number of devices, or a new request can be added for that, as well as a new event type for when devices come and go.

I think all device requests have empty fields which can be used to specify which device the request applies to, so that applications can properly enumerate all devices. And although I'm pretty sure currently all unused fields are set to 0, it's probably prudent to explicitly ignore it if the client has not activated multi-device mode.

In reality since the new protocol was introduced, the biggest difficulty I think is in how to handle multiple devices within the daemon at this point. Beyond the refactoring, there's also the issue of what to do with configuration. Things like device sensitivity, axis and button mappings and so on, are really device-specific, but currently there's just a single global configuration, and changing that would necessarilly complicate the configuration syntax. But I guess one step at a time...

ggoretkin-bdai commented 10 months ago

If we're adding things to the protocol, I think binding a device to each client (and having the client open multiple connections) feels ackward.

but it seems like this was the intent of

https://github.com/FreeSpacenav/spacenavd/blob/d186c5d6ae854be44737bc8f9b250c7b8afbfe78/src/event.c#L357-L360

is there an alternative intent that I'm missing?

jtsiomb commented 10 months ago

No, you're right, that was the intention behind this mechanism, and I guess it's also useful to be able to select a specific device and receive only events from that. But:

  1. This is basically an incomplete stub. client->dev is always null at this point, defaulting to the first device.
  2. This bug report, unless I'm reading it incorrectly, is about receiving events from all devices, and being able to discriminate between them. Implementing that on a per-client device association is possible, but awkward.
ggoretkin-bdai commented 10 months ago

as well as a new event type for when devices come and go.

I think this is already in place with event_dev / spnav_event_dev

https://github.com/FreeSpacenav/spacenavd/blob/a2d121af16628e98f523c2746ccad7b6e72c8dca/src/dev.c#L212-L220

jtsiomb commented 10 months ago

Nice! I forgot I had done that. Unfortunately I also forgot to add the various device operations (like DEV_ADD) in the protocol header. So that part is covered, and the omissions are easily mended.

lmh12138 commented 1 week ago

I'd like to know how the adaptation for multiple mice is progressing, I really need this feature now!