async def receive_data(self, hid_device, output_file=None): while True: data = await hid_device.read(size=255, timeout=3) if self._stop_reading: break elif not data: continue # add byte for input report data = b'\xa1' + data input_report = InputReport(list(data)) # check if input report is spi flash read reply if input_report.get_input_report_id() != 0x21: continue try: sub_command_id = input_report.get_reply_to_subcommand_id() if sub_command_id != SubCommand.SPI_FLASH_READ: continue except NotImplementedError: continue assert input_report.get_ack() == 0x90 reply = input_report.get_sub_command_reply_data() # parse offset offset = 0 digit = 1 for i in range(4): offset += reply[i] * digit digit *= 0x100 size = reply[4] # parse spi flash data assert len(reply) >= 5 + size spi_data = reply[5:5 + size] # check if received data is currently requested if self.pending_request is None or self.pending_request[ 0] != offset or self.pending_request[1] != size: continue # notify spi request sender that the data is received self.pending_request[2].set() logger.info(f'received offset {offset}, size {size} - {spi_data}') # write data to file if output_file is not None: output_file.write(bytes(spi_data))
async def input_report_mode_full(self): """ Continuously sends: 0x30 input reports containing the controller state OR 0x31 input reports containing the controller state and nfc data """ if self.transport.is_reading(): raise ValueError('Transport must be paused in full input report mode') # send state at 66Hz send_delay = 0.015 await asyncio.sleep(send_delay) last_send_time = time.time() input_report = InputReport() input_report.set_vibrator_input() input_report.set_misc() if self._input_report_mode is None: raise ValueError('Input report mode is not set.') input_report.set_input_report_id(self._input_report_mode) reader = asyncio.ensure_future(self.transport.read()) try: while True: reply_send = False if reader.done(): data = await reader reader = asyncio.ensure_future(self.transport.read()) try: report = OutputReport(list(data)) output_report_id = report.get_output_report_id() if output_report_id == OutputReportID.RUMBLE_ONLY: # TODO pass elif output_report_id == OutputReportID.SUB_COMMAND: reply_send = await self._reply_to_sub_command(report) elif output_report_id == OutputReportID.REQUEST_IR_NFC_MCU: # TODO NFC raise NotImplementedError('NFC communictation is not implemented.') else: logger.warning(f'Report unknown output report "{output_report_id}" - IGNORE') except ValueError as v_err: logger.warning(f'Report parsing error "{v_err}" - IGNORE') except NotImplementedError as err: logger.warning(err) if reply_send: # Hack: Adding a delay here to avoid flooding during pairing await asyncio.sleep(0.3) else: # write 0x30 input report. input_report.set_6axis_data(*self._controller_state.axis_state.get_6axis()) # TODO NFC - set nfc data if input_report.get_input_report_id() == 0x31: pass await self.write(input_report) # calculate delay current_time = time.time() time_delta = time.time() - last_send_time sleep_time = send_delay - time_delta last_send_time = current_time if sleep_time < 0: # logger.warning(f'Code is running {abs(sleep_time)} s too slow!') sleep_time = 0 await asyncio.sleep(sleep_time) except NotConnectedError as err: # Stop 0x30 input report mode if disconnected. logger.error(err) finally: # cleanup self._input_report_mode = None # cancel the reader with suppress(asyncio.CancelledError, NotConnectedError): if reader.cancel(): await reader