Solved Reading /dev/sysmouse as a user

Hey,

I'm currently attempting to implement mouse support in a user application, and I'm kinda hitting a bit of a roadblock here. It seems as though and it would make sense that /dev/sysmouse (from sysmouse(4)) should be readable by the user, as it's used for X and because it runs on top of /dev/ums*, which itself is readable by the user when it's not busy (i.e. when moused(8) isn't running), but it isn't:

Code:
% cat /dev/sysmouse
cat: /dev/sysmouse: Permission denied

Now what I can do is change the group ownership of /dev/sysmouse to be operator and then make it readable by the operator group:

Code:
# ll /dev/sysmouse
crw-------  1 root  wheel      0x19  4 Sep 12:11 /dev/sysmouse
# chown :operator /dev/sysmouse
# chmod g+r /dev/sysmouse
# ll /dev/sysmouse
crw-r-----  1 root  operator   0x19  4 Sep 12:11 /dev/sysmouse

and this works, I can then read it as a user (assuming he's part of the operator group), but it's still got me wondering 1. if playing around with permissions like this is allowed/recommended 2. why /dev/sysmouse isn't available to the user in the first place.

Thanks for your time!
 
Last edited by a moderator:
from sysmouse(4)) should be readable by the user,
Code:
The console driver, in conjunction	with the mouse daemon moused(8), sup-
     plies mouse data to the user process in the standardized way via the
     sysmouse driver.
User process refers to something that runs in userland (moused(8) for example, is a user process), as opposed to something running in kernel space. It doesn't necessary mean that a user is able to access it.
 
Thank you for your answer!

User process refers to something that runs in userland (moused(8) for example, is a user process), as opposed to something running in kernel space. It doesn't necessary mean that a user is able to access it.

Yup, I understand that, I meant it should be readable by the user in that that's what seems like would make most sense. If you can change video modes with ioctls as a regular user, why is it that /dev/sysmouse can't even be read by users part of the wheel group, and what the best way then of accessing the mouse as a user is then.

As an aside, how do you add the section number to manual page references?
 
Hey,

I'm currently attempting to implement mouse support in a user application, and I'm kinda hitting a bit of a roadblock here. It seems as though and it would make sense that /dev/sysmouse (from sysmouse(4)) should be readable by the user, as it's used for X and because it runs on top of /dev/ums*, which itself is readable by the user when it's not busy (i.e. when moused(8) isn't running), but it isn't:

It's fairly explicit in the manual page:
The user process which wants to utilize mouse operation simply opens
/dev/sysmouse with a open(2) call and reads mouse data from the device
via read(2). Make sure that moused(8) is running, otherwise the user
process will not see any data coming from the mouse.


What's failing? Also, note, this is NOT the usage of mouse in X, this is allowing a console mouse AND a X windows mouse.
(I know nothing about mouse programming; it shows... :))



Code:
% cat /dev/sysmouse
cat: /dev/sysmouse: Permission denied

It would be cat < /dev/sysmouse.

Now what I can do is change the group ownership of /dev/sysmouse to be operator and then make it readable by the operator group:

Code:
# ll /dev/sysmouse
crw-------  1 root  wheel      0x19  4 Sep 12:11 /dev/sysmouse

Not a good idea, long term, as it will be changed. Best to use devfs(8) for that. (In the short term, it's ok).

(I am finding the editing of quotes in this forum software to be close to stupid nowadays!)
 
Maybe i get something wrong, but if it's an X application, why don't you just use a GUI toolkit like GTK3 to query the cursor position? Or even plain Xlib?
 
I'm assuming/guessing it's a console application, probably using ncurses while running X, so that they both can share the mouse.
 
Use [MAN=N]program[/MAN]
Thanks!

What's failing? Also, note, this is NOT the usage of mouse in X, this is allowing a console mouse AND a X windows mouse.
(I know nothing about mouse programming; it shows... :))
I'm unable, as any user which is not the root user, to open an read from /dev/sysmouse, and I was wondering what the best way to work around this would be then.

It would be cat < /dev/sysmouse.
What does that change? AFAIK cat will read from stdin by default and from its first argument if specified otherwise. So redirecting a file to it as stdin should do nothing a priori, right?

Maybe i get something wrong, but if it's an X application, why don't you just use a GUI toolkit like GTK3 to query the cursor position? Or even plain Xlib?
Yeah I have two backends for my application; one for X, which uses XCB to get mouse input, and one which interacts directly with the VGA framebuffer in the console for systems with no X server, for which I'd need some kind of mouse input, which I was hoping /dev/sysmouse would provide.

Not a good idea, long term, as it will be changed. Best to use devfs(8) for that. (In the short term, it's ok).
Ok great, that's exactly what I was looking for! Relatively new to FreeBSD, still getting the hang of a few things and learning what the best practices are 😄 So basically what worked for me was adding the following two lines to /etc/devfs.conf:

Code:
own sysmouse root:operator
perm sysmouse 0640

to change the group of /dev/sysmouse to be operator, so that it can then be made to be readable & writable by the owner (root) and readable by users in the operator group. After running service devfs restart, /dev/sysmouse has the correct permissions.

Thank you to everyone for your answers!
 
Sorry to bump this post again, but for anyone wanting to interact with the mouse while in the console, a much better solution I found than reading from /dev/sysmouse is to use the CONS_MOUSECTL ioctl. Here's some example code I wrote quickly if this helps anyone:

C:
#include <stdio.h>
#include <unistd.h>

#include <sys/fbio.h> // for 'video_info_t'
#include <sys/consio.h>

static mouse_info_t mouse_info;

static int set_position(int x, int y) {
    mouse_info.operation = MOUSE_MOVEABS;

    mouse_info.u.data.x = x;
    mouse_info.u.data.y = y;

    if (ioctl(0, CONS_MOUSECTL, &mouse_info) < 0) {
        return -1;
    }

    return 0;
}

int main(void) {
    // centre mouse
    
    int mode;
    if (ioctl(0, CONS_GET, &mode) < 0) goto error;

    video_info_t mode_info = { .vi_mode = mode };
    if (ioctl(0, CONS_MODEINFO, &mode_info) < 0) goto error;

    if (set_position(mode_info.vi_width / 2, mode_info.vi_height / 2) < 0) {
        goto error;
    }

    // main loop

    while (1) {
        mouse_info.operation = MOUSE_GETINFO;
        
        if (ioctl(0, CONS_MOUSECTL, &mouse_info) < 0) {
            goto error;
        }

        struct {
            unsigned left   : 1;
            unsigned middle : 1;
            unsigned right  : 1;
        } buttons;

        memcpy(&buttons, &mouse_info.u.data.buttons, sizeof buttons);

        printf("x = %d, y = %d\n", mouse_info.u.data.x, mouse_info.u.data.y);
        printf("left = %d, right = %d, middle = %d\n\n", buttons.left, buttons.right, buttons.middle);

        usleep(50000);
    }

    return 0;

error:
    
    return 1;
}
 
Yes, i tried it both in a virtual console without X and in a terminal emulator under X.
Result is the same:
Code:
[xxx@xxx ~/development]$ ./mouse
[xxx@xxx ~/development]$ echo $?
1
[xxx@xxx ~/development]$

Edit:

Note 1:
I get a warning regarding memcpy
Code:
[xxx@xxx ~/development]$ cc -o mouse mouse.c
mouse.c:52:9: warning: implicitly declaring library function 'memcpy' with type 'void *(void *, const void *, unsigned long)' [-Wimplicit-function-declaration]
        memcpy(&buttons, &mouse_info.u.data.buttons, sizeof buttons);
        ^
mouse.c:52:9: note: include the header <string.h> or explicitly provide a declaration for 'memcpy'
1 warning generated.
Including the header string.h gets rid of the warning but does not solve the problem.

Note 2:
I run arm64/aarch64 on a Raspberry Pi 400, maybe that's something to consider.
 
Hmm... could you test where it's exiting with some printf calls before the return statements?
 
Hmm... could you test where it's exiting with some printf calls before the return statements?
It exits here:
Code:
    if (set_position(mode_info.vi_width / 2, mode_info.vi_height / 2) < 0) {
        printf("3\n");
        goto error;
    }

that means
Code:
if (ioctl(0, CONS_MOUSECTL, &mouse_info) < 0)
fails.
 
The memcpy warning is nothing to worry about. I haven't yet tried FreeBSD on the Raspberry Pi, perhaps the console driver isn't yet fully featured and doesn't support CONS_MOUSECTL. Not something I'm too fussed about, my application is only meant for x86/x64, but it may be something I'll look into 🙃
 
Back
Top