diff --git a/joycontrol/button_state.py b/joycontrol/button_state.py index 0bc51b5..8cf1fd5 100644 --- a/joycontrol/button_state.py +++ b/joycontrol/button_state.py @@ -72,4 +72,4 @@ class ButtonState: yield self._byte_3 def clear(self): - self._byte_1 = self._byte_2 = self._byte_3 = 0 \ No newline at end of file + self._byte_1 = self._byte_2 = self._byte_3 = 0 diff --git a/joycontrol/controller_state.py b/joycontrol/controller_state.py index 2e0ba69..952c012 100644 --- a/joycontrol/controller_state.py +++ b/joycontrol/controller_state.py @@ -8,11 +8,12 @@ class ControllerState: def __init__(self, transport: asyncio.Transport, protocol: ControllerProtocol): super().__init__() self.transport = transport - self.protocol = protocol + self.input_report = self.protocol.get_button_input_report() + async def send(self): - await self.protocol.button_input_report.write(self.transport) + await self.input_report.write(self.transport) async def connect(self): """ @@ -27,7 +28,7 @@ class ControllerState: """ Sets the button status bytes in the input report """ - self.protocol.button_input_report.set_button_status(button_state) + self.input_report.set_button_status(button_state) def set_stick_state(self): """ @@ -36,3 +37,20 @@ class ControllerState: raise NotImplementedError() +async def button_push(controller_state, button, sec=0.1): + button_state = ButtonState() + + # push button + getattr(button_state, button)() + + # send report + controller_state.set_button_state(button_state) + await controller_state.send() + await asyncio.sleep(sec) + + # release button + getattr(button_state, button)() + + # send report + controller_state.set_button_state(button_state) + await controller_state.send() \ No newline at end of file diff --git a/joycontrol/protocol.py b/joycontrol/protocol.py index 5cba0c4..1faa160 100644 --- a/joycontrol/protocol.py +++ b/joycontrol/protocol.py @@ -22,12 +22,15 @@ class ControllerProtocol(BaseProtocol): self.transport = None # This must always be an 0x21 input report to be compatible with button events - self.button_input_report = InputReport() - self.button_input_report.set_input_report_id(0x21) - self.button_input_report.set_misc() + self._button_input_report = InputReport() + self._button_input_report.set_input_report_id(0x21) + self._button_input_report.set_misc() self._data_received = asyncio.Event() + def get_button_input_report(self): + return self._button_input_report + async def wait_for_output_report(self): self._data_received.clear() await self._data_received.wait() @@ -79,44 +82,44 @@ class ControllerProtocol(BaseProtocol): assert address is not None bd_address = list(map(lambda x: int(x, 16), address[0].split(':'))) - self.button_input_report.set_misc() - self.button_input_report.set_ack(0x82) - self.button_input_report.sub_0x02_device_info(bd_address, controller=self.controller) + self._button_input_report.set_misc() + self._button_input_report.set_ack(0x82) + self._button_input_report.sub_0x02_device_info(bd_address, controller=self.controller) - await self.button_input_report.write(self.transport) + await self._button_input_report.write(self.transport) async def _command_set_shipment_state(self, output_report): - self.button_input_report.set_misc() - self.button_input_report.set_ack(0x80) - self.button_input_report.sub_0x08_shipment() + self._button_input_report.set_misc() + self._button_input_report.set_ack(0x80) + self._button_input_report.sub_0x08_shipment() - await self.button_input_report.write(self.transport) + await self._button_input_report.write(self.transport) async def _command_spi_flash_read(self, output_report): - self.button_input_report.set_misc() - self.button_input_report.set_ack(0x90) - self.button_input_report.sub_0x10_spi_flash_read(output_report) + self._button_input_report.set_misc() + self._button_input_report.set_ack(0x90) + self._button_input_report.sub_0x10_spi_flash_read(output_report) - await self.button_input_report.write(self.transport) + await self._button_input_report.write(self.transport) async def _command_set_input_report_mode(self, output_report): - self.button_input_report.set_misc() - self.button_input_report.set_ack(0x80) - self.button_input_report.sub_0x03_set_input_report_mode() + self._button_input_report.set_misc() + self._button_input_report.set_ack(0x80) + self._button_input_report.sub_0x03_set_input_report_mode() - await self.button_input_report.write(self.transport) + await self._button_input_report.write(self.transport) async def _command_trigger_buttons_elapsed_time(self, output_report): - self.button_input_report.set_misc() - self.button_input_report.set_ack(0x83) - self.button_input_report.sub_0x04_trigger_buttons_elapsed_time() + self._button_input_report.set_misc() + self._button_input_report.set_ack(0x83) + self._button_input_report.sub_0x04_trigger_buttons_elapsed_time() - await self.button_input_report.write(self.transport) + await self._button_input_report.write(self.transport) async def _enable_6axis_sensor(self, output_report): - self.button_input_report.set_misc() - self.button_input_report.set_ack(0x80) + self._button_input_report.set_misc() + self._button_input_report.set_ack(0x80) - self.button_input_report.reply_to_subcommand_id(0x40) + self._button_input_report.reply_to_subcommand_id(0x40) - await self.button_input_report.write(self.transport) + await self._button_input_report.write(self.transport) diff --git a/joycontrol/server.py b/joycontrol/server.py index 252e747..b99dd7b 100644 --- a/joycontrol/server.py +++ b/joycontrol/server.py @@ -1,15 +1,15 @@ import asyncio import logging -import os import socket -import joycontrol +import pkg_resources + from joycontrol import utils from joycontrol.device import HidDevice from joycontrol.report import InputReport from joycontrol.transport import L2CAP_Transport -PROFILE_PATH = os.path.join(os.path.dirname(joycontrol.__file__), 'profile/sdp_record_hid.xml') +PROFILE_PATH = pkg_resources.resource_filename('joycontrol', 'profile/sdp_record_hid.xml') logger = logging.getLogger(__name__) diff --git a/run_test_controller_buttons.py b/run_test_controller_buttons.py index 80cff91..9933db9 100644 --- a/run_test_controller_buttons.py +++ b/run_test_controller_buttons.py @@ -3,32 +3,13 @@ import logging import os from joycontrol import logging_default as log -from joycontrol.controller_state import ButtonState, ControllerState +from joycontrol.controller_state import ControllerState, button_push from joycontrol.protocol import controller_protocol_factory, Controller from joycontrol.server import create_hid_server logger = logging.getLogger(__name__) -async def button_push(controller_state, button, sec=0.1): - button_state = ButtonState() - - # push button - getattr(button_state, button)() - - # send report - controller_state.set_button_state(button_state) - await controller_state.send() - await asyncio.sleep(sec) - - # release button - getattr(button_state, button)() - - # send report - controller_state.set_button_state(button_state) - await controller_state.send() - - async def test_controller_buttons(controller_state: ControllerState): """ Goes to the "Test Controller Buttons" menu and presses all buttons diff --git a/setup.py b/setup.py index fa71630..facd416 100644 --- a/setup.py +++ b/setup.py @@ -7,8 +7,10 @@ setup(name='joycontrol', author_email='martinro@informatik.hu-berlin.de', description='Emulate Nintendo Switch Controllers over Bluetooth', packages=find_packages(), + package_data={'joycontrol': ['profile/sdp_record_hid.xml']}, zip_safe=False, install_requires=[ # TODO ] ) +