Finish v1

This commit is contained in:
Marc Riera Irigoyen 2022-10-20 23:17:06 +02:00
parent fd032173b8
commit 7223f7741c
6 changed files with 117 additions and 162 deletions

View file

@ -1,17 +1,116 @@
from enum import IntEnum
from events.input import InputEvent
from evdev import ecodes, UInput, AbsInfo
class EmulatedGamepad:
class GamepadType(IntEnum):
PC2HANDLE = 0
PS1 = 1
N64 = 1
class PC2HandleGamepad(EmulatedGamepad):
# Mapping
# A: BTN_EAST
# B: BTN_SOUTH
# C: BTN_NORTH
# D: BTN_WEST
# SL: BTN_SELECT
# ST: BTN_START
# BRAKE: ABS_X
# POWER: ABS_Y
def __init__(self):
self.type = self.GamepadType.PC2HANDLE
self.capabilities = {
ecodes.EV_KEY : [ecodes.BTN_NORTH, ecodes.BTN_SOUTH, ecodes.BTN_EAST, ecodes.BTN_WEST, ecodes.BTN_SELECT, ecodes.BTN_START],
ecodes.EV_ABS : [(ecodes.ABS_X, AbsInfo(0, 0, 255, 0, 0, 0)), (ecodes.ABS_Y, AbsInfo(0, 0, 255, 0, 0, 0))]
}
self.brake_notches = (0x79, 0x8A, 0x94, 0x9A, 0xA2, 0xA8, 0xAF, 0xB2, 0xB5, 0xB9)
self.power_notches = (0x81, 0x6D, 0x54, 0x3F, 0x21, 0x00)
def write_input(self, event: InputEvent):
print(str(event.type) + ": " + str(event.data))
def start(self):
self.ui = UInput(self.capabilities, vendor=0x0AE4, product=0x0003, name='Emulated DGOC-44U')
def stop(self):
self.ui.close()
def write_input(self, event):
match event.type:
case (InputEvent.EventType.RELEASE_BUTTON | InputEvent.EventType.PRESS_BUTTON):
match event.data:
case InputEvent.Button.BUTTON_A:
self.ui.write(ecodes.EV_KEY, ecodes.BTN_EAST, event.type)
case InputEvent.Button.BUTTON_B:
self.ui.write(ecodes.EV_KEY, ecodes.BTN_SOUTH, event.type)
case InputEvent.Button.BUTTON_C:
self.ui.write(ecodes.EV_KEY, ecodes.BTN_NORTH, event.type)
case InputEvent.Button.BUTTON_D:
self.ui.write(ecodes.EV_KEY, ecodes.BTN_WEST, event.type)
case InputEvent.Button.BUTTON_SELECT:
self.ui.write(ecodes.EV_KEY, ecodes.BTN_SELECT, event.type)
case InputEvent.Button.BUTTON_START:
self.ui.write(ecodes.EV_KEY, ecodes.BTN_START, event.type)
case InputEvent.Button.BUTTON_UP:
self.ui.write(ecodes.EV_KEY, ecodes.BTN_SELECT, event.type)
self.ui.write(ecodes.EV_KEY, ecodes.BTN_WEST, event.type)
case InputEvent.Button.BUTTON_DOWN:
self.ui.write(ecodes.EV_KEY, ecodes.BTN_SELECT, event.type)
self.ui.write(ecodes.EV_KEY, ecodes.BTN_SOUTH, event.type)
case InputEvent.Button.BUTTON_LEFT:
self.ui.write(ecodes.EV_KEY, ecodes.BTN_SELECT, event.type)
self.ui.write(ecodes.EV_KEY, ecodes.BTN_EAST, event.type)
case InputEvent.Button.BUTTON_RIGHT:
self.ui.write(ecodes.EV_KEY, ecodes.BTN_SELECT, event.type)
self.ui.write(ecodes.EV_KEY, ecodes.BTN_NORTH, event.type)
case InputEvent.EventType.BRAKE_NOTCH:
self.ui.write(ecodes.EV_ABS, ecodes.ABS_X, self.brake_notches[event.data])
case InputEvent.EventType.POWER_NOTCH:
self.ui.write(ecodes.EV_ABS, ecodes.ABS_Y, self.power_notches[event.data])
self.ui.syn()
class N64Gamepad(EmulatedGamepad):
def __init__(self):
self.type = self.GamepadType.N64
self.capabilities = {
ecodes.EV_KEY : [ecodes.BTN_NORTH, ecodes.BTN_SOUTH, ecodes.BTN_EAST, ecodes.BTN_WEST, ecodes.BTN_TL, ecodes.BTN_TR,
ecodes.BTN_TL2, ecodes.BTN_TR2, ecodes.BTN_SELECT, ecodes.BTN_START, ecodes.BTN_THUMBL, ecodes.BTN_THUMBR,
ecodes.BTN_MODE, ecodes.BTN_DPAD_UP, ecodes.BTN_DPAD_DOWN, ecodes.BTN_DPAD_LEFT, ecodes.BTN_DPAD_RIGHT],
ecodes.EV_ABS : [(ecodes.ABS_X, AbsInfo(0, 0, 255, 0, 0, 0)), (ecodes.ABS_Y, AbsInfo(0, 0, 255, 0, 0, 0)),
(ecodes.ABS_RX, AbsInfo(0, 0, 255, 0, 0, 0)), (ecodes.ABS_RY, AbsInfo(0, 0, 255, 0, 0, 0))]
}
def start(self):
self.ui = UInput(self.capabilities, vendor=0x54C, product=0x268, name='Sony PLAYSTATION(R)3 Controller')
def stop(self):
self.ui.close()
def write_input(self, event):
match event.type:
case (InputEvent.EventType.RELEASE_BUTTON | InputEvent.EventType.PRESS_BUTTON):
match event.data:
case InputEvent.Button.BUTTON_A:
self.ui.write(ecodes.EV_KEY, ecodes.BTN_EAST, event.type)
case InputEvent.Button.BUTTON_B:
self.ui.write(ecodes.EV_KEY, ecodes.BTN_SOUTH, event.type)
case InputEvent.Button.BUTTON_C:
self.ui.write(ecodes.EV_KEY, ecodes.BTN_WEST, event.type)
case InputEvent.Button.BUTTON_D:
self.ui.write(ecodes.EV_KEY, ecodes.BTN_MODE, event.type)
case InputEvent.Button.BUTTON_SELECT:
self.ui.write(ecodes.EV_KEY, ecodes.BTN_MODE, event.type)
case InputEvent.Button.BUTTON_START:
self.ui.write(ecodes.EV_KEY, ecodes.BTN_START, event.type)
case InputEvent.EventType.POWER_NOTCH:
match event.data:
case 0:
self.ui.write(ecodes.EV_KEY, ecodes.BTN_DPAD_RIGHT, 0)
self.ui.write(ecodes.EV_KEY, ecodes.BTN_DPAD_UP, 1)
self.ui.write(ecodes.EV_KEY, ecodes.BTN_TL2, 1)
case 1:
self.ui.write(ecodes.EV_KEY, ecodes.BTN_DPAD_RIGHT, 1)
self.ui.write(ecodes.EV_KEY, ecodes.BTN_DPAD_UP, 0)
self.ui.write(ecodes.EV_KEY, ecodes.BTN_TL2, 1)
self.ui.syn()

View file

@ -77,29 +77,23 @@ class SwitchGamepad(PhysicalGamepad):
if event.type == evdev.ecodes.EV_ABS and event.code == evdev.ecodes.ABS_HAT0X:
match event.value:
case -1: # LEFT
input_events.append(InputEvent(InputEvent.EventType.PRESS_BUTTON, InputEvent.Button.BUTTON_SELECT))
input_events.append(InputEvent(InputEvent.EventType.PRESS_BUTTON, InputEvent.Button.BUTTON_LEFT))
input_events.append(InputEvent(InputEvent.EventType.RELEASE_BUTTON, InputEvent.Button.BUTTON_RIGHT))
input_events.append(InputEvent(InputEvent.EventType.PRESS_BUTTON, InputEvent.Button.BUTTON_LEFT))
case 1: # RIGHT
input_events.append(InputEvent(InputEvent.EventType.PRESS_BUTTON, InputEvent.Button.BUTTON_SELECT))
input_events.append(InputEvent(InputEvent.EventType.RELEASE_BUTTON, InputEvent.Button.BUTTON_LEFT))
input_events.append(InputEvent(InputEvent.EventType.PRESS_BUTTON, InputEvent.Button.BUTTON_RIGHT))
case _: # NONE
input_events.append(InputEvent(InputEvent.EventType.RELEASE_BUTTON, InputEvent.Button.BUTTON_SELECT))
input_events.append(InputEvent(InputEvent.EventType.RELEASE_BUTTON, InputEvent.Button.BUTTON_LEFT))
input_events.append(InputEvent(InputEvent.EventType.RELEASE_BUTTON, InputEvent.Button.BUTTON_RIGHT))
if event.type == evdev.ecodes.EV_ABS and event.code == evdev.ecodes.ABS_HAT0Y:
match event.value:
case -1: # UP
input_events.append(InputEvent(InputEvent.EventType.PRESS_BUTTON, InputEvent.Button.BUTTON_SELECT))
input_events.append(InputEvent(InputEvent.EventType.PRESS_BUTTON, InputEvent.Button.BUTTON_UP))
input_events.append(InputEvent(InputEvent.EventType.RELEASE_BUTTON, InputEvent.Button.BUTTON_DOWN))
input_events.append(InputEvent(InputEvent.EventType.PRESS_BUTTON, InputEvent.Button.BUTTON_UP))
case 1: # DOWN
input_events.append(InputEvent(InputEvent.EventType.PRESS_BUTTON, InputEvent.Button.BUTTON_SELECT))
input_events.append(InputEvent(InputEvent.EventType.RELEASE_BUTTON, InputEvent.Button.BUTTON_UP))
input_events.append(InputEvent(InputEvent.EventType.PRESS_BUTTON, InputEvent.Button.BUTTON_DOWN))
case _: # NONE
input_events.append(InputEvent(InputEvent.EventType.RELEASE_BUTTON, InputEvent.Button.BUTTON_SELECT))
input_events.append(InputEvent(InputEvent.EventType.RELEASE_BUTTON, InputEvent.Button.BUTTON_UP))
input_events.append(InputEvent(InputEvent.EventType.RELEASE_BUTTON, InputEvent.Button.BUTTON_DOWN))
if event.type == evdev.ecodes.EV_ABS and event.code == evdev.ecodes.ABS_Y:

View file

@ -30,10 +30,16 @@ class MainWindow(QMainWindow):
self._gui.pushButton_emulatedControllerStop.clicked.connect(self.controller_emulator_stop)
self._gui.pushButton_emulatedControllerStop.setVisible(False)
self.populate_controller_combobox()
def closeEvent(self, event):
self._emuthread_stop.set()
def populate_controller_combobox(self):
self._gui.comboBox_emulatedControllerModel.addItem("PC two-handle controller (DGOC-44U)", gamepad_emulated.PC2HandleGamepad())
#self._gui.comboBox_emulatedControllerModel.addItem("N64 two-handle controller (TCPP-20003)", gamepad_emulated.N64Gamepad())
self._gui.comboBox_emulatedControllerModel.setCurrentIndex(0)
def controller_list_refresh(self):
self.gamepad_model.beginResetModel()
self.gamepad_model.gamepads = self._gamepad_handler.find_gamepads()
@ -69,7 +75,7 @@ class MainWindow(QMainWindow):
rows = self._gui.tableView_physicalControllerList.selectionModel().selectedRows()
if rows:
gamepad = self.gamepad_model.gamepads[rows[0].row()]
emulated_gamepad = gamepad_emulated.PC2HandleGamepad()
emulated_gamepad = self._gui.comboBox_emulatedControllerModel.itemData(self._gui.comboBox_emulatedControllerModel.currentIndex())
self._emuthread = threading.Thread(target=self._gamepad_handler.run_gamepad_emulator, args=(gamepad, emulated_gamepad, self._emuthread_stop))
self._emuthread.start()

View file

@ -48,6 +48,7 @@ class Ui_MainWindow(object):
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_physicalControllerActions.addItem(spacerItem)
self.pushButton_physicalControllerConfig = QtWidgets.QPushButton(self.groupBox_physicalControllers)
self.pushButton_physicalControllerConfig.setEnabled(False)
self.pushButton_physicalControllerConfig.setObjectName("pushButton_physicalControllerConfig")
self.horizontalLayout_physicalControllerActions.addWidget(self.pushButton_physicalControllerConfig)
self.verticalLayout_2.addLayout(self.horizontalLayout_physicalControllerActions)

View file

@ -93,6 +93,9 @@
</item>
<item>
<widget class="QPushButton" name="pushButton_physicalControllerConfig">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Configuration</string>
</property>

View file

@ -16,6 +16,7 @@ class GamepadHandler:
return gamepads
def run_gamepad_emulator(gamepad, emulated_gamepad, stop_event):
emulated_gamepad.start()
while not stop_event.is_set():
events = gamepad.read_input()
if events is not None:
@ -23,153 +24,4 @@ class GamepadHandler:
if event.type == input_events.InputEvent.EventType.ERROR:
break
emulated_gamepad.write_input(event)
""" cap = {
e.EV_KEY : [e.BTN_NORTH, e.BTN_SOUTH, e.BTN_EAST, e.BTN_WEST, e.BTN_SELECT, e.BTN_START],
e.EV_ABS : [(e.ABS_X, AbsInfo(0, 0, 255, 0, 0, 0)), (e.ABS_Y, AbsInfo(0, 0, 255, 0, 0, 0))]
}
# Mapping
# A: BTN_EAST
# B: BTN_SOUTH
# C: BTN_NORTH
# D: BTN_WEST
# SL: BTN_SELECT
# ST: BTN_START
# BRAKE: ABS_X
# POWER: ABS_Y
mascon_switch = None
devices = [InputDevice(path) for path in list_devices()]
for device in devices:
dev_name = [device.info.vendor, device.info.product, device.name]
if dev_name == [0x0f0d, 0x00c1, "One Handle MasCon for Nintendo Switch"]:
mascon_switch = device
break
if mascon_switch is None:
print("No supported controller found.")
exit()
ui = UInput(cap, vendor=0x0AE4, product=0x0003, name='Emulated DGOC-44U')
mascon_switch.grab()
for event in mascon_switch.read_loop():
if event.type == e.EV_KEY:
match event.code:
case 304: # Y
ui.write(e.EV_KEY, e.BTN_EAST, event.value)
ui.syn()
case 305: # B
ui.write(e.EV_KEY, e.BTN_SOUTH, event.value)
ui.syn()
case 306: # A
ui.write(e.EV_KEY, e.BTN_NORTH, event.value)
ui.syn()
case 307: # X
ui.write(e.EV_KEY, e.BTN_WEST, event.value)
ui.syn()
case 312: # MINUS
ui.write(e.EV_KEY, e.BTN_SELECT, event.value)
ui.syn()
case 313: # PLUS
ui.write(e.EV_KEY, e.BTN_START, event.value)
ui.syn()
if event.type == e.EV_ABS and event.code == e.ABS_HAT0X:
match event.value:
case -1: # LEFT
ui.write(e.EV_KEY, e.BTN_SELECT, 1)
ui.write(e.EV_KEY, e.BTN_EAST, 1)
ui.write(e.EV_KEY, e.BTN_NORTH, 0)
ui.syn()
case 1: # RIGHT
ui.write(e.EV_KEY, e.BTN_SELECT, 1)
ui.write(e.EV_KEY, e.BTN_EAST, 0)
ui.write(e.EV_KEY, e.BTN_NORTH, 1)
ui.syn()
case _: # NONE
ui.write(e.EV_KEY, e.BTN_SELECT, 0)
ui.write(e.EV_KEY, e.BTN_EAST, 0)
ui.write(e.EV_KEY, e.BTN_NORTH, 0)
ui.syn()
if event.type == e.EV_ABS and event.code == e.ABS_HAT0Y:
match event.value:
case -1: # UP
ui.write(e.EV_KEY, e.BTN_SELECT, 1)
ui.write(e.EV_KEY, e.BTN_WEST, 1)
ui.write(e.EV_KEY, e.BTN_SOUTH, 0)
ui.syn()
case 1: # DOWN
ui.write(e.EV_KEY, e.BTN_SELECT, 1)
ui.write(e.EV_KEY, e.BTN_WEST, 0)
ui.write(e.EV_KEY, e.BTN_SOUTH, 1)
ui.syn()
case _: # NONE
ui.write(e.EV_KEY, e.BTN_SELECT, 0)
ui.write(e.EV_KEY, e.BTN_WEST, 0)
ui.write(e.EV_KEY, e.BTN_SOUTH, 0)
ui.syn()
if event.type == e.EV_ABS and event.code == e.ABS_Y:
match event.value:
case 0x0: # EMG
ui.write(e.EV_ABS, e.ABS_X, 0xB9)
ui.write(e.EV_ABS, e.ABS_Y, 0x81)
ui.syn()
case 0x5:
ui.write(e.EV_ABS, e.ABS_X, 0xB5)
ui.write(e.EV_ABS, e.ABS_Y, 0x81)
ui.syn()
case 0x13:
ui.write(e.EV_ABS, e.ABS_X, 0xB2)
ui.write(e.EV_ABS, e.ABS_Y, 0x81)
ui.syn()
case 0x20:
ui.write(e.EV_ABS, e.ABS_X, 0xAF)
ui.write(e.EV_ABS, e.ABS_Y, 0x81)
ui.syn()
case 0x2E:
ui.write(e.EV_ABS, e.ABS_X, 0xA8)
ui.write(e.EV_ABS, e.ABS_Y, 0x81)
ui.syn()
case 0x3C:
ui.write(e.EV_ABS, e.ABS_X, 0xA2)
ui.write(e.EV_ABS, e.ABS_Y, 0x81)
ui.syn()
case 0x49:
ui.write(e.EV_ABS, e.ABS_X, 0x9A)
ui.write(e.EV_ABS, e.ABS_Y, 0x81)
ui.syn()
case 0x57:
ui.write(e.EV_ABS, e.ABS_X, 0x94)
ui.write(e.EV_ABS, e.ABS_Y, 0x81)
ui.syn()
case 0x65:
ui.write(e.EV_ABS, e.ABS_X, 0x8A)
ui.write(e.EV_ABS, e.ABS_Y, 0x81)
ui.syn()
case 0x80:
ui.write(e.EV_ABS, e.ABS_X, 0x79)
ui.write(e.EV_ABS, e.ABS_Y, 0x81)
ui.syn()
case 0x9F:
ui.write(e.EV_ABS, e.ABS_X, 0x79)
ui.write(e.EV_ABS, e.ABS_Y, 0x6D)
ui.syn()
case 0xB7:
ui.write(e.EV_ABS, e.ABS_X, 0x79)
ui.write(e.EV_ABS, e.ABS_Y, 0x54)
ui.syn()
case 0xCE:
ui.write(e.EV_ABS, e.ABS_X, 0x79)
ui.write(e.EV_ABS, e.ABS_Y, 0x3F)
ui.syn()
case 0xE6:
ui.write(e.EV_ABS, e.ABS_X, 0x79)
ui.write(e.EV_ABS, e.ABS_Y, 0x21)
ui.syn()
case 0xFF:
ui.write(e.EV_ABS, e.ABS_X, 0x79)
ui.write(e.EV_ABS, e.ABS_Y, 0x00)
ui.syn()
"""
emulated_gamepad.stop()