Authored by Benjamin Tissoires

ratbag-emu diagrams

class diagram

class BaseDevice {
+simulate_actions(action, duration)
class UHID {
set_report(req, rnum, rtype, data)
class Endpoint
class Brain {
+set_report(req, rnum, rtype, data)
class PhysHWComponent {
class LED {
class RGBLed {
class HIDActuator {
+get_HID_data(data, action)
class OpticalSensor {
class Button
class Wheel
class LogitechHIDPP20Brain
class SteelSeriesBrain
BaseDevice o-- Endpoint : <dict> endpoints
BaseDevice o-- Brain : brain
BaseDevice o-- PhysHWComponent : <dict> physical_parts
BaseDevice o-- HIDActuator: <dict> HID_parts
UHID <|-- Endpoint
PhysHWComponent <|-- LED
PhysHWComponent <|-- RGBLed
Brain <|-- LogitechHIDPP20Brain
Brain <|-- SteelSeriesBrain

Sequence diagram for dispatch():

participant CI client
participant BaseDevice
participant @UHID
CI client->> @UHID: dispatch()
@UHID-->> Endpoint: _process_one_event()
Endpoint->>BaseDevice: set_report(req, rnum, rtype, data)
BaseDevice->>Brain: set_report(req, rnum, rtype, data)
Brain->>BaseDevice: set_new_state("RGB1", red: 255)
BaseDevice->>RGBLed: set_new_state(red: 255)

Sequence diagram for simulate_actions() (refresh rate: 1Hz):

CI client->>BaseDevice: simulate_actions(move: {x:3}, duration: 3s)
BaseDevice->>BaseDevice : individual_action = {move: {x: 1}}
BaseDevice->>BaseDevice : data = {}
BaseDevice->>HIDActuator: for each: get_HID_data(data, individual_action)
HIDHWComponent->>HIDActuator: <OpticalSensor> `if move in action and in action[move]:  data[self.report_id]`[] = 1
BaseDevice->>Endpoint : for each: call_input_event(data[endpoint.report_id])
BaseDevice->>Endpoint : for each: call_input_event(data[endpoint.report_id])
BaseDevice->>Endpoint : for each: call_input_event(data[endpoint.report_id])


  • Brain can not inherit from UHID or EndPoint: it needs to process all endpoints in one place
  • rate is global to SimulatedDevice because it's a parameter only used in simulate_actions(), and it doesn't really make sense to have a special class for it
2.41 KB
  • @FFY00:

    For instantiating a Logitech G900 for example: you define a logitech-g900.yaml:

    logitech G900:
      type: ratbag-device
        - 05 00 00...
        - 05 00 00...
        - 05 00 00...
        type: LogitechHIDPP20Brain
             - 0x0001
             - 0x8001
        - RGB0:
          type: RGBLed
        - x:
          type: OpticalSensor
            default_dpi: 1000
        - y:
          type: OpticalSensor
            default_dpi: 1000
        - wheel:
          type: Wheel
        - b0:
          type: Button
        - b1:
          type: Button
        - b2:
          type: Button
        - b3:
          type: Button
        - b4:
          type: Button
        - b5:
          type: Button
        - b6:
          type: Button
        - b7:
          type: Button
        - b8:
          type: Button
        - b9:
          type: Button
        - b10:
          type: Button

    BasedDevice then has a class method that takes a dictionary (parsed from the YAML above) and instantiate the matching BaseDevice with all of its components.

    If you want to be fancy, you can implement an include keyword (like @whot did in, so you can define a generic mouse without a brain with the common x, y, wheel and 3 buttons.

Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment