Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Introduce HIDProperty #48

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open

Introduce HIDProperty #48

wants to merge 7 commits into from

Conversation

FFY00
Copy link
Member

@FFY00 FFY00 commented Mar 23, 2020

Replaces #45

This deals with the issues from #45 in a nicer way. Instead of a HID Actuator, like suggested, we introduce HIDProperty. Each endpoint has a list of properties which is populated by parsing the report descriptor.

HIDProperty has a populate method which receives an action after it has been updated by the device actuators, and populates a list of HID events with the according HID data. This replaces the Device._simulate_action_*.

The idea is to subclass HIDProperty for each supported HID data type (eg. AxisProperty).

This allows us to drop ActionType as everything is now dynamically resolved to HID properties.

What do you think @bentiss? Does this resolve your concerns?

@FFY00 FFY00 requested a review from bentiss March 23, 2020 21:03
Copy link
Collaborator

@bentiss bentiss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I am truly lost here and I can't follow you.

There are barely no commit message explaining the changes so I have to re-read all of the code to get what you are changing.
The PR itself has some explanations, but they need to be put in the commits themselves, not just in the PR message. This PR message will eventually get lost, when the commit descriptions aren't (especially if we switch to gitlab in the future).

It seems to me that the HIDProperty class is the equivalent of what I had in mind for the actuator, so I can't figure out the change in naming.

So instead of answering with words, I'll need from you a class diagram.

Which means, I'm going to block this PR until we get #27 sorted out, with an up to date class diagram. Then, this PR will need to have the matching changes in the diagram, and an explanation on how it is now used.

Sorry for being rude, but I am in the dark for understanding the high level logic of all of this, and I have a feeling you are too.

Edit: s/I am in the black/I am in the dark/

@FFY00
Copy link
Member Author

FFY00 commented Mar 24, 2020

There are barely no commit message explaining the changes so I have to re-read all of the code to get what you are changing.
The PR itself has some explanations, but they need to be put in the commits themselves, not just in the PR message. This PR message will eventually get lost, when the commit descriptions aren't (especially if we switch to gitlab in the future).

Right, sorry. I will try to fix that moving forward.

It seems to me that the HIDProperty class is the equivalent of what I had in mind for the actuator, so I can't figure out the change in naming.

Well, I was not entirely sure what you had in mind for the HID Actuator. It seemed like this but I didn't know if this was exactly what you had in mind. HIDProperty seemed like a better name to me, but we can change it if you want.

So instead of answering with words, I'll need from you a class diagram.

Which means, I'm going to block this PR until we get #27 sorted out, with an up to date class diagram. Then, this PR will need to have the matching changes in the diagram, and an explanation on how it is now used.

I was planning to do that next, but yeah, it probably makes more sense to do it now.

@FFY00 FFY00 force-pushed the hid-actuator branch 6 times, most recently from e2b6898 to 95f7bc0 Compare March 25, 2020 15:39
@bentiss bentiss mentioned this pull request Mar 25, 2020
FFY00 added 6 commits March 25, 2020 18:30
Introduces a HIDProperty class. A HID property represents a data type
from the HID report descriptor (eg. X, Y, etc axis, buttons, etc).

Each HIDProperty must implement a populate() method which receives a
high-level action and a HID event array. It will populate the HID event
array based on the high-level action.

Example:
    (definition)
    ```python
    class ExampleButtonProperty(HIDProperty):
        ...
        def populate(action, packets):
            for packet in packets:
                if 'buttons' in action:
                    for key, val in action['buttons'].items():
                        setattr(packet, f'b{key}', 1 if val else 0)
    ```

    (usage)
    ```python
    ...

    action = {
        ...
        'buttons': {
            0: True,
            1: False,
            2: True,
        }
        ...
    }

    packets = []
    for _ in range(packet_count):
        packets.append(EventData())

    '''
    endpoint.populate_hid_data() will call populate() for each HID property
    in the endpoint, includes our populate() method defined above
    '''
    endpoint.populate_hid_data(action, packets)

    for packet in packets:
        endpoint.send(endpoint.create_report(packets))
    ```

Note: This is a simple example using buttons, there's not much to do
here, we just set the button value in the events. A example where more
things need to happen is in the axis. I didn't provide the axis as an
example because the code is a bit more involved and harder to read.
This should provide an overview on how the different components are
supposed to be used togather.

The idea is to define a HIDProperty for each HID usage and teach it how
to handle that data.

This patch just introduces the class and makes Endpoint to hold a list
the of HID properties. Integration with the rest of the codebase comes
in the next patches.

Signed-off-by: Filipe Laíns <lains@archlinux.org>
This patch introduces a new HIDProperty, AxisProperty, which knows how
to handle the Axis Usages from the Generic Desktop Page.

Signed-off-by: Filipe Laíns <lains@archlinux.org>
…rsion

In a previous patch we introduced HIDProperty, classes which subclass
it (eg. AxisProperty) should know how to handle specific HID usages.

This patch replaces the current _simulate_action_* routines with HID
properties. Instead of teaching Device how to handle every single HID
usage we define HID properties.

Each endpoint has a list of properties which is dynamically discovered
from its report descriptor. When it's time to perform an action we
generate the a HID event list (the lenght is based on the action
duration and the device report rate) and ask each endpoint to populate.

Signed-off-by: Filipe Laíns <lains@archlinux.org>
Signed-off-by: Filipe Laíns <lains@archlinux.org>
Signed-off-by: Filipe Laíns <lains@archlinux.org>
Signed-off-by: Filipe Laíns <lains@archlinux.org>
@FFY00 FFY00 requested a review from bentiss March 25, 2020 18:31
@FFY00
Copy link
Member Author

FFY00 commented Mar 25, 2020

We now have docs and I've added descriptions to the commits. I think the descriptions I added should be enough but please let me know if there is something you can't follow.

@FFY00
Copy link
Member Author

FFY00 commented Apr 3, 2020

@bentiss ping

@bentiss
Copy link
Collaborator

bentiss commented Apr 3, 2020

I still don't get the separation between the Actuator, and the HIDProperty.

I would really like you to try to see if the code is not cleaner if:

  • HIDProperty inherits from Actuator
  • HIDProperty references the EndPoint
  • you might have more than one Actuator per type, given the report descriptor
  • instead of having transform() and populate(), you just have transform(), which gets reimplemented in HIDProperty by taking the old code of populate()

@FFY00
Copy link
Member Author

FFY00 commented Apr 8, 2020

Before I make a proper reply I just want to clarify some things.

I still don't get the separation between the Actuator, and the HIDProperty.

I would really like you to try to see if the code is not cleaner if:

* `HIDProperty` inherits from `Actuator`

This means each HIDProperty will inherit from each Actuator, right? If not, could you please clarify what you mean?

* `HIDProperty` references the `EndPoint`

Do you mean that HIDProperty will use Endpoint, and Endpoint won't use HIDProperty? For eg. HIDProperty will use Endpoint to send the HID report.

* you might have more than one `Actuator` per type, given the report descriptor

* instead of having `transform()` and `populate()`, you just have `transform()`, which gets reimplemented in `HIDProperty` by taking the old code of `populate()`

This might seem a bit basic but I just want to make sure we are on the same page.

@bentiss
Copy link
Collaborator

bentiss commented Apr 9, 2020

Before I make a proper reply I just want to clarify some things.

I still don't get the separation between the Actuator, and the HIDProperty.
I would really like you to try to see if the code is not cleaner if:

* `HIDProperty` inherits from `Actuator`

This means each HIDProperty will inherit from each Actuator, right? If not, could you please clarify what you mean?

Yes, you can have multiple (HID)Actuators.

* `HIDProperty` references the `EndPoint`

Do you mean that HIDProperty will use Endpoint, and Endpoint won't use HIDProperty? For eg. HIDProperty will use Endpoint to send the HID report.

I mean that the HIDProperty should be aware of its endpoint. So that when you ask for a HID translation, you can ask for "give me the HID translation for report number 2", and the HIDProperty will either fill in the report if it is lined to report number 2 or will silently pass if it's not.

* you might have more than one `Actuator` per type, given the report descriptor

* instead of having `transform()` and `populate()`, you just have `transform()`, which gets reimplemented in `HIDProperty` by taking the old code of `populate()`

This might seem a bit basic but I just want to make sure we are on the same page.

@FFY00
Copy link
Member Author

FFY00 commented Apr 20, 2020

I still don't get the separation between the Actuator, and the HIDProperty.
I would really like you to try to see if the code is not cleaner if:

* `HIDProperty` inherits from `Actuator`

Okay, the separation is simple.

Actuators transform event data:

  • Axis movement, based on DPI
  • Button mappings
  • etc
    So, they essentially provide a frontend in the API. The user says "move 5 mm", we know we want to move 5000 dots, the user says "press button 5", we known we want to send the key A. The idea is for them to just transforms values based on the internal configuration.

HIDProperty takes the event and transforms it into a list of objects (HID events) to be sent by hidtools. It essentially converts our event into raw HID data.

The event data will be restructured, the current one is just a prototype. My idea was to use the actuators to entirely replace actions, for eg. when we are working with macros, a "press button 6" event would be replaced with a "move 50 dots on the X axis and press KEY_A down for 1sec" event.

This means each HIDProperty will inherit from each Actuator, right? If not, could you please clarify what you mean?

Yes, you can have multiple (HID)Actuators.

If we bind them together we would end up with something like AxisSensorHIDActuator, AxisCustomSensorHIDActuator, AxisOtherCustomSensorHIDActuator, etc. they would all have the same logic, inherited from AxisHIDActuator, but we would need to define a (HID)Actuator for each type of actuator.

The HID actuators are also tied to the HID properties in the report descriptor (eg. logical max/min), so I think it makes more sense to have a list of them in each endpoint.

I made a diagram, should make things much easier for you to visualize: https://gitlab.freedesktop.org/snippets/971

I think the depth of this diagram shows the design better than the other one.

* `HIDProperty` references the `EndPoint`

Do you mean that HIDProperty will use Endpoint, and Endpoint won't use HIDProperty? For eg. HIDProperty will use Endpoint to send the HID report.

I mean that the HIDProperty should be aware of its endpoint. So that when you ask for a HID translation, you can ask for "give me the HID translation for report number 2", and the HIDProperty will either fill in the report if it is lined to report number 2 or will silently pass if it's not.

Okay, the question to ask here is who needs to ask HIDProperty for that? I only think that makes sense if we implement what you suggested above, for my suggestion it does not really fit. We can come back to this when we reach a conclusion in the discussion above.

Signed-off-by: Filipe Laíns <lains@archlinux.org>
@lgtm-com
Copy link

lgtm-com bot commented Apr 20, 2020

This pull request introduces 2 alerts when merging 7f63157 into 5930050 - view on LGTM.com

new alerts:

  • 2 for Module is imported with 'import' and 'import from'

@libratbag libratbag deleted a comment from lgtm-com bot Apr 20, 2020
@FFY00
Copy link
Member Author

FFY00 commented Apr 29, 2020

@bentiss friendly ping, if you have time.

@bentiss
Copy link
Collaborator

bentiss commented Apr 30, 2020

OK, I'll try to not be too angry there, but I am.

The event data will be restructured, the current one is just a prototype. My idea was to use the actuators to entirely replace actions, for eg. when we are working with macros, a "press button 6" event would be replaced with a "move 50 dots on the X axis and press KEY_A down for 1sec" event.

On a PR, we work on the current code, not the future one. Either you have something, you submit it and we discuss, but I can not review something which is just in your head.

That being said, nothing I told you prevent your idea to be working.

If we bind them together we would end up with something like AxisSensorHIDActuator, AxisCustomSensorHIDActuator, AxisOtherCustomSensorHIDActuator, etc. they would all have the same logic, inherited from AxisHIDActuator, but we would need to define a (HID)Actuator for each type of actuator.

Yes, and?

The HID actuators are also tied to the HID properties in the report descriptor (eg. logical max/min), so I think it makes more sense to have a list of them in each endpoint.

I don't.

Okay, the question to ask here is who needs to ask HIDProperty for that? I only think that makes sense if we implement what you suggested above, for my suggestion it does not really fit. We can come back to this when we reach a conclusion in the discussion above.

No, there is no question. I asked you to do one thing. I detailed it:

* `HIDProperty` inherits from `Actuator`
* `HIDProperty` references the `EndPoint`
* you might have more than one `Actuator` per type, given the report descriptor
* instead of having `transform()` and `populate()`, you just have `transform()`, which gets reimplemented in `HIDProperty` by taking the old code of `populate()`

And all you are doing is not what I asked. So this is getting really tiring.

Make use of subclassing to separate the concerns (the "action" from the HID conversion), and this should give a better and cleaner code. I am not asking something really complex, I am just asking for a change in how the design is.

If you don't like my idea, I don't care. I want you to implement it nonetheless, to show me what it look like, and then we can decide which one is better. But spending countless time just bikeshedding over a design when every single decision needs to be justified is time definitively lost where we could have made a lot of progress.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants