Esempio n. 1
0
    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))
Esempio n. 2
0
    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