diff --git a/protocol.py b/protocol.py index 83e761a..a25010b 100644 --- a/protocol.py +++ b/protocol.py @@ -53,6 +53,8 @@ class ControllerProtocol(BaseProtocol): logger.error(f'No sub command found') elif sub_command == SubCommand.REQUEST_DEVICE_INFO: await self._command_request_device_info(report) + elif sub_command == SubCommand.SET_SHIPMENT_STATE: + await self._command_set_shipment_state(report) elif sub_command == SubCommand.NOT_IMPLEMENTED: logger.error(f'Sub command not implemented') @@ -64,10 +66,20 @@ class ControllerProtocol(BaseProtocol): input_report = InputReport() input_report.set_input_report_id(0x21) input_report.set_misc() - input_report.set_button_status() - input_report.set_left_analog_stick() - input_report.set_right_analog_stick() - input_report.set_vibrator_input() + input_report.set_ack(0x82) + #input_report.set_button_status() + #input_report.set_left_analog_stick() + #input_report.set_right_analog_stick() + #input_report.set_vibrator_input() input_report.sub_0x2_device_info(bd_address) - asyncio.ensure_future(self.transport.write(bytes(input_report))) + asyncio.ensure_future(self.transport.write(input_report)) + + async def _command_set_shipment_state(self, output_report): + input_report = InputReport() + input_report.set_input_report_id(0x21) + input_report.set_misc() + input_report.set_ack(0x80) + input_report.sub_0x8_shipment() + + asyncio.ensure_future(self.transport.write(input_report)) diff --git a/report.py b/report.py index 14d146e..c5290fd 100644 --- a/report.py +++ b/report.py @@ -31,8 +31,12 @@ class InputReport: # battery level + connection info self.data[3] = 0x8E - # ACK byte for subcmd reply - self.data[14] = 0x82 + def set_ack(self, ack): + """ + ACK byte for subcmd reply + TODO + """ + self.data[14] = ack def set_button_status(self): """ @@ -86,9 +90,14 @@ class InputReport: def __bytes__(self): return bytes(self.data) + def sub_0x8_shipment(self): + # reply to sub command ID + self.data[15] = 0x08 + class SubCommand(Enum): REQUEST_DEVICE_INFO = auto() + SET_SHIPMENT_STATE = auto() NOT_IMPLEMENTED = auto() @@ -100,8 +109,11 @@ class OutputReport: def get_sub_command(self): print('subcommand:', self.data[11]) - if self.data[11] == 0x02: + sub_command_byte = self.data[11] + if sub_command_byte == 0x02: return SubCommand.REQUEST_DEVICE_INFO + elif sub_command_byte == 0x08: + return SubCommand.SET_SHIPMENT_STATE else: return None diff --git a/transport.py b/transport.py index 1c2915a..2793905 100644 --- a/transport.py +++ b/transport.py @@ -2,6 +2,8 @@ import asyncio import logging from typing import Any +from report import InputReport + logger = logging.getLogger(__name__) @@ -18,14 +20,14 @@ class L2CAP_Transport(asyncio.Transport): 'sockname': self._sock.getsockname() } - print("peer", self._sock.getpeername()) - self._read_thread = asyncio.ensure_future(self._read()) self._is_closing = False self._is_reading = asyncio.Event() self._is_reading.set() + self._input_report_timer = 0x00 + async def _read(self): try: while True: @@ -58,8 +60,18 @@ class L2CAP_Transport(asyncio.Transport): return super().get_write_buffer_size() async def write(self, data: Any) -> None: - logger.debug(f'sending "{data}"') - await self._loop.sock_sendall(self._sock, data) + + if isinstance(data, bytes): + _bytes = data + elif isinstance(data, InputReport): + data.set_timer(self._input_report_timer) + self._input_report_timer = (self._input_report_timer + 1) % 256 + _bytes = bytes(data) + else: + raise ValueError('data must be bytes or InputReport') + + logger.debug(f'sending "{_bytes}"') + await self._loop.sock_sendall(self._sock, _bytes) def abort(self) -> None: super().abort()