richardanaya / conifer

Apache License 2.0
37 stars 4 forks source link

Supporting Raspberry Pi #1

Open richardanaya opened 4 years ago

richardanaya commented 4 years ago

@nbrr

I'd love for us to figure out some generic way we can understand the touch screen capabilities of our respective devices in an hardware agnostic manner.

I think the secrets exist somewhere in

/sys/class/input/event*

I'm wondering if we can scan over the event drivers and figure out which device is a touch screen and their min max details.

richardanaya commented 4 years ago

I'm working on a little micro library to suss out the input devices using sysfs https://github.com/richardanaya/sysfs_input

i'd be curious what your raspberry pi says with

cargo run --example scan
nbrr commented 4 years ago

Besides input file path, the one thing I had to adapt on my rpi running Raspbian, is that the timeval of the input event was given on 8 bytes instead of 16. Here I abstracted this in a struct with impl for reading the events. This should probably be turned unto a trait with impl for 8- or 16-bytes timeval. I assume the difference comes from that Raspbian is a 32bit system, but I haven't found details on 32/64bits difference in the behaviour of input event. Properly implementing input events (spec here) certainly deserves to be delegated to a crate on its own. The only relevant rate I found so far is input-event-codes which only contains constants.

Here is the scan on my rpi, the touchscreen is input0:

Ok(
    [
        Input(
            InputDevice {
                name: "MX Keys Consumer Control",
                file_name: "input3",
                capabilities: [
                    InputCapability {
                        name: "rel",
                        raw_value: "40",
                    },
                    InputCapability {
                        name: "abs",
                        raw_value: "1 0",
                    },
                    InputCapability {
                        name: "ff",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "led",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "sw",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "key",
                        raw_value: "300ff 0 0 0 0 483ffff 17aff32d bf544446 0 0 1 130ff3 8b17c000 677bfa d9415fed 9ed680 4400 0 10000002",
                    },
                    InputCapability {
                        name: "msc",
                        raw_value: "10",
                    },
                    InputCapability {
                        name: "snd",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "ev",
                        raw_value: "1f",
                    },
                ],
                properties: "0",
            },
        ),
        Event(
            EventDevice {
                file_name: "event3",
                device_name: "input3",
            },
        ),
        Input(
            InputDevice {
                name: "MX Keys Keyboard",
                file_name: "input1",
                capabilities: [
                    InputCapability {
                        name: "rel",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "abs",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "ff",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "led",
                        raw_value: "1f",
                    },
                    InputCapability {
                        name: "sw",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "key",
                        raw_value: "10000 7 ff800000 7ff febeffdf ffefffff ffffffff fffffffe",
                    },
                    InputCapability {
                        name: "msc",
                        raw_value: "10",
                    },
                    InputCapability {
                        name: "snd",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "ev",
                        raw_value: "120013",
                    },
                ],
                properties: "0",
            },
        ),
        Event(
            EventDevice {
                file_name: "event1",
                device_name: "input1",
            },
        ),
        Event(
            EventDevice {
                file_name: "event4",
                device_name: "input5",
            },
        ),
        Input(
            InputDevice {
                name: "MX Keys Mouse",
                file_name: "input2",
                capabilities: [
                    InputCapability {
                        name: "rel",
                        raw_value: "143",
                    },
                    InputCapability {
                        name: "abs",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "ff",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "led",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "sw",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "key",
                        raw_value: "ffff0000 0 0 0 0 0 0 0 0",
                    },
                    InputCapability {
                        name: "msc",
                        raw_value: "10",
                    },
                    InputCapability {
                        name: "snd",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "ev",
                        raw_value: "17",
                    },
                ],
                properties: "0",
            },
        ),
        Event(
            EventDevice {
                file_name: "event2",
                device_name: "input2",
            },
        ),
        Input(
            InputDevice {
                name: "FT5406 memory based driver",
                file_name: "input0",
                capabilities: [
                    InputCapability {
                        name: "rel",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "abs",
                        raw_value: "2608000 3",
                    },
                    InputCapability {
                        name: "ff",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "led",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "sw",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "key",
                        raw_value: "400 0 0 0 0 0 0 0 0 0 0",
                    },
                    InputCapability {
                        name: "msc",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "snd",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "ev",
                        raw_value: "b",
                    },
                ],
                properties: "2",
            },
        ),
        Event(
            EventDevice {
                file_name: "event0",
                device_name: "input0",
            },
        ),
        Input(
            InputDevice {
                name: "MX Ergo Mouse",
                file_name: "input5",
                capabilities: [
                    InputCapability {
                        name: "rel",
                        raw_value: "143",
                    },
                    InputCapability {
                        name: "abs",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "ff",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "led",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "sw",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "key",
                        raw_value: "ffff0000 0 0 0 0 0 0 0 0",
                    },
                    InputCapability {
                        name: "msc",
                        raw_value: "10",
                    },
                    InputCapability {
                        name: "snd",
                        raw_value: "0",
                    },
                    InputCapability {
                        name: "ev",
                        raw_value: "17",
                    },
                ],
                properties: "0",
            },
        ),
    ],
)
richardanaya commented 4 years ago

I really like they direction you are going with having a stateful struct that holds the configuration of the target file and other params. Ideally we could auto detect all this stuff, but it would be an improvement I think even having your ability to manually put it together. :)

What do you think about renaming Config to Device? Since it probably will contain both config info for input as well as frame buffer ( maybe other device buttons some day? like volume buttons?)

richardanaya commented 4 years ago

I noticed that your touchscreen appears to be

name: "FT5406 memory based driver", file_name: "input0"

I'm noticing that it's the only device that has a non-trivial "abs" value, i'm wondering if we could use that as some kind of ability to detect the device. I'd really love to figure out how to decode those magical values in "abs". I need to research that a bit.

nbrr commented 4 years ago

I'm noticing that it's the only device that has a non-trivial "abs" value, i'm wondering if we could use that as some kind of ability to detect the device. I'd really love to figure out how to decode those magical values in "abs". I need to research that a bit.

It's actually all in the document I mentioned that I've begun reading, here. Actually no you are specifically mentioning the content of /sys/class/input/event*/device/capabilities/. I believe this is an array listing what kind of events are supported by the device (briefly mentioned here but I need to find better reference.

As for the document I previously linked, it gives a few ways to identify a touchscreen from the events, I don't know how reliable it is as it seems conventional. ABS describes absolute coordinates, while REL describes movement relative to the last known position. So ABS seems to be characteristic of touch devices, while REL is more apt to describe mouse movement.

nbrr commented 4 years ago

All this seems to be a fragment of evdev for which there is already a few crates.

richardanaya commented 4 years ago

‘evdev’ looks like it has what we need. The api is a little esoteric, going to look at it a bit. I wonder if it handles time stamp differences.

richardanaya commented 4 years ago

@nbrr checkout the new example I added in conifer https://github.com/richardanaya/conifer/blob/master/examples/scan.rs :)

cargo run --example scan
nbrr commented 4 years ago

‘evdev’ looks like it has what we need. The api is a little esoteric, going to look at it a bit. I wonder if it handles time stamp differences.

It seems to be doing fine, I guess it is because it uses libc FFI which certainly knows about it. I rewrote lib using the evdev crate, it is a bit cleaner since it doesn't need to read bytes. evdev doesn't seem to give higher level interpretation of the event bits.

nbrr commented 4 years ago

@nbrr checkout the new example I added in conifer https://github.com/richardanaya/conifer/blob/master/examples/scan.rs :)

cargo run --example scan

Looks good!

name: FT5406 memory based driver
file: File {
    fd: 8,
    path: "/dev/input/event0",
    read: true,
    write: true,
}
abs: input_absinfo {
    value: 722,
    minimum: 0,
    maximum: 800,
    fuzz: 0,
    flat: 0,
    resolution: 0,
}
richardanaya commented 4 years ago

@nbrr did you want to try to add in auto detect to your config struct? Or if you want I could do it, we could PR your stuff into mainline conifer. I liked the direction you were going with Config

nbrr commented 4 years ago

For now I PR'd that Config. I did not include changes I made not to color 2 pixels per touch as it's clumsy and I'd like to make it nice.

What behaviour did you have in mind in case there are several available devices? How about the framebuffer? And input width/height are in a way dependent on the hardware capacity but also depend on what surface the user actually wants to use.

richardanaya commented 4 years ago

I think for basic auto detect v1, using fb0 makes sense, and we could use the first device that has touch events and absolute events flag capability. Just even something basic that makes running conifer on PinePhone or RP effortlessly would be awesome.

For auto detect v2, since we are in console, if we truly do see multiple options we can’t decide between we could make a simple text entry “choose what frame buffer you want to use?” Perhaps.

richardanaya commented 4 years ago

I think the only thing really remaining in this issue is updating examples when we are ready, and coming up with some common way to exit for our demos.

nbrr commented 4 years ago

Also need to make sure that 32/64bits timeval is properly dealt with.

richardanaya commented 4 years ago

@nbrr

Could you describe for me again what issues remain with timeval now on your machine?

The way we are building things up looks fairly generic.

for ev in self.input_device.events_no_sync().unwrap() {
                let e = match (ev._type, ev.code, ev.value, ev.time) {
                    (EV_ABS, ABS_X, x, time) => {
                        InputEvent::PartialX(x as isize, Timeval::from_timeval(time))