Exemple #1
0
    def run_with_result(self, command: BaseCommand, *args) -> bytes:
        """
        Run a command against the Kraken hardware and fetch the result

        :param command: The command tuple
        :param args: Argument list (varargs)

        :return: Raw response bytes
        """
        try:
            with self.device_open():
                if not self._run_command(command, *args):
                    return None

                self._last_cmd_time = smart_delay(DELAY_TIME,
                                                  self._last_cmd_time, 0)
                resp = self._dev.read(REPORT_LENGTH_IN, timeout_ms=500)
                self._hexdump(resp, '<-- ')

                if resp is None or len(resp) == 0:
                    return None

                assert resp[0] == REPORT_ID_IN, \
                    'Inbound report should have id %02x (was %02x)' % \
                    (REPORT_ID_IN, resp[0])

                return resp[1:command.length + 1]

        except (OSError, IOError) as err:
            self.logger.exception('Caught exception running command',
                                  exc_info=err)

        return None
Exemple #2
0
    def _run_command(self, command: BaseCommand, *args) -> bool:
        try:
            data = UChromaHeadset._pack_request(command, *args)
            self._hexdump(data, '--> ')
            self._last_cmd_time = smart_delay(DELAY_TIME, self._last_cmd_time, 0)
            self._dev.write(data, report_id=to_byte(REPORT_ID_OUT))
            return True

        except (OSError, IOError) as err:
            self.logger.exception('Caught exception running command', exc_info=err)

        return False
Exemple #3
0
    def run(self, delay: float = None, timeout_cb=None) -> bool:
        """
        Run this report and retrieve the result from the hardware.

        Sends the feature report and parses the result. A small delay
        is required between calls to the hardware or a BUSY status
        will be returned. This delay may need adjusted on a per-model
        basis.

        If debug loglevel is enabled, the raw report data from both
        the request and the response will be logged.

        :param delay: Time to delay between requests (defaults to 0.005 sec)
        :param timeout_cb: Callback to run when a TIMEOUT is returned

        :return: The parsed result from the hardware
        """
        if delay is None:
            delay = RazerReport.CMD_DELAY_TIME

        retry_count = 3

        with self._driver.device_open():
            while retry_count > 0:
                try:
                    req = self._pack_request()
                    self._hexdump(req, '--> ')
                    if self._remaining_packets == 0:
                        self._driver.last_cmd_time = smart_delay(
                            delay, self._driver.last_cmd_time,
                            self._remaining_packets)
                    self._driver.hid.send_feature_report(
                        req, self.REQ_REPORT_ID)
                    if self._remaining_packets > 0:
                        return True

                    self._driver.last_cmd_time = smart_delay(
                        delay, self._driver.last_cmd_time,
                        self._remaining_packets)
                    resp = self._driver.hid.get_feature_report(
                        self.RSP_REPORT_ID, self.BUF_SIZE)
                    self._hexdump(resp, '<-- ')
                    if self._unpack_response(resp):
                        if timeout_cb is not None:
                            timeout_cb(self.status, None)
                        return True

                    if self.status == Status.FAIL or self.status == Status.UNSUPPORTED:
                        self._logger.error("Command failed with status %s",
                                           self.status.name)
                        return False

                    if timeout_cb is not None and self.status == Status.TIMEOUT:
                        timeout_cb(self.status, self.result)
                        return False

                    self._logger.warning(
                        "Retrying request due to status %s (%d)",
                        self.status.name, retry_count)

                    time.sleep(0.1)

                    retry_count -= 1

                except (OSError, IOError):
                    self._status = Status.OSERROR
                    raise

        return False