implemented 0x30 input report

This commit is contained in:
Robert Martin
2020-02-05 16:37:27 +09:00
parent 6f11ee0b22
commit 7d5a4f05fe
8 changed files with 291 additions and 176 deletions
+139 -32
View File
@@ -4,6 +4,7 @@ from asyncio import BaseTransport, BaseProtocol
from typing import Optional, Union, Tuple, Text
from joycontrol.controller import Controller
from joycontrol.controller_state import ControllerState
from joycontrol.report import OutputReport, SubCommand, InputReport, OutputReportID
logger = logging.getLogger(__name__)
@@ -21,15 +22,27 @@ 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._data_received = asyncio.Event()
def get_button_input_report(self):
return self._button_input_report
self._controller_state = ControllerState(self)
self._pending_write = None
self._pending_input_report = None
self._0x30_input_report_sender = None
self.sig_wait_player_lights = asyncio.Event()
async def write(self, input_report: InputReport):
# set button and TODO: stick date
if self._controller_state.button_state is not None:
input_report.set_button_status(self._controller_state.button_state)
self._controller_state.sig_is_send.set()
await self.transport.write(input_report)
def get_controller_state(self):
return self._controller_state
async def wait_for_output_report(self):
self._data_received.clear()
@@ -45,6 +58,27 @@ class ControllerProtocol(BaseProtocol):
def error_received(self, exc: Exception) -> None:
raise NotImplementedError()
async def send_0x30_input_reports(self):
input_report = InputReport()
input_report.set_input_report_id(0x30)
input_report.set_misc()
while True:
# TODO: set sensor data
input_report.set_6axis_data()
await self.write(input_report)
"""
if self.controller == Controller.PRO_CONTROLLER:
# send state at 120Hz if Pro Controller
await asyncio.sleep(1 / 120)
else:
# send state at 60Hz
await asyncio.sleep(1 / 60)
"""
await asyncio.sleep(1 / 30)
async def report_received(self, data: Union[bytes, Text], addr: Tuple[str, int]) -> None:
self._data_received.set()
@@ -87,6 +121,19 @@ class ControllerProtocol(BaseProtocol):
elif sub_command == SubCommand.TRIGGER_BUTTONS_ELAPSED_TIME:
await self._command_trigger_buttons_elapsed_time(report)
elif sub_command == SubCommand.ENABLE_6AXIS_SENSOR:
await self._command_enable_6axis_sensor(report)
elif sub_command == SubCommand.ENABLE_VIBRATION:
await self._command_enable_vibration(report)
elif sub_command == SubCommand.SET_NFC_IR_MCU_CONFIG:
await self._command_set_nfc_ir_mcu_config(report)
elif sub_command == SubCommand.SET_PLAYER_LIGHTS:
await self._command_set_player_lights(report)
else:
logger.warning(f'Sub command 0x{sub_command.value:02x} not implemented - ignoring')
#elif output_report_id == OutputReportID.RUMBLE_ONLY:
@@ -95,48 +142,108 @@ class ControllerProtocol(BaseProtocol):
logger.warning(f'Output report {output_report_id} not implemented - ignoring')
async def _command_request_device_info(self, output_report):
input_report = InputReport()
input_report.set_input_report_id(0x21)
input_report.set_misc()
address = self.transport.get_extra_info('sockname')
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)
input_report.set_ack(0x82)
input_report.sub_0x02_device_info(bd_address, controller=self.controller)
await self._button_input_report.write(self.transport)
await self.write(input_report)
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()
input_report = InputReport()
input_report.set_input_report_id(0x21)
input_report.set_misc()
await self._button_input_report.write(self.transport)
input_report.set_ack(0x80)
input_report.reply_to_subcommand_id(0x08)
await self.write(input_report)
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)
input_report = InputReport()
input_report.set_input_report_id(0x21)
input_report.set_misc()
await self._button_input_report.write(self.transport)
input_report.set_ack(0x90)
input_report.sub_0x10_spi_flash_read(output_report)
await self.write(input_report)
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()
if output_report.data[12] == 0x30:
logger.info('Setting input report mode to 0x30...')
# start sending 0x30 input reports
assert self._0x30_input_report_sender is None
self._0x30_input_report_sender = asyncio.ensure_future(self.send_0x30_input_reports())
await self._button_input_report.write(self.transport)
input_report = InputReport()
input_report.set_input_report_id(0x21)
input_report.set_misc()
input_report.set_ack(0x80)
input_report.reply_to_subcommand_id(0x03)
await self.write(input_report)
else:
logger.error(f'input report mode {output_report.data[12]} not implemented - ignoring request')
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()
input_report = InputReport()
input_report.set_input_report_id(0x21)
input_report.set_misc()
await self._button_input_report.write(self.transport)
input_report.set_ack(0x83)
input_report.sub_0x04_trigger_buttons_elapsed_time()
async def _enable_6axis_sensor(self, output_report):
self._button_input_report.set_misc()
self._button_input_report.set_ack(0x80)
await self.write(input_report)
self._button_input_report.reply_to_subcommand_id(0x40)
async def _command_enable_6axis_sensor(self, output_report):
input_report = InputReport()
input_report.set_input_report_id(0x21)
input_report.set_misc()
await self._button_input_report.write(self.transport)
input_report.set_ack(0x80)
input_report.reply_to_subcommand_id(0x40)
await self.write(input_report)
async def _command_enable_vibration(self, output_report):
input_report = InputReport()
input_report.set_input_report_id(0x21)
input_report.set_misc()
input_report.set_ack(0x80)
input_report.reply_to_subcommand_id(SubCommand.ENABLE_VIBRATION.value)
await self.write(input_report)
async def _command_set_nfc_ir_mcu_config(self, output_report):
input_report = InputReport()
input_report.set_input_report_id(0x21)
input_report.set_misc()
input_report.set_ack(0xA0)
input_report.reply_to_subcommand_id(SubCommand.SET_NFC_IR_MCU_CONFIG.value)
for i in range(16, 51):
input_report.data[i] = 0xFF
await self.write(input_report)
async def _command_set_player_lights(self, output_report):
input_report = InputReport()
input_report.set_input_report_id(0x21)
input_report.set_misc()
input_report.set_ack(0x80)
input_report.reply_to_subcommand_id(SubCommand.SET_PLAYER_LIGHTS.value)
await self.write(input_report)
self.sig_wait_player_lights.set()