mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-01-29 00:51:53 +08:00
refactoring
This commit is contained in:
@@ -91,7 +91,7 @@ class _TempRequestError(_RequestError):
|
||||
|
||||
# =====
|
||||
class BasePhyConnection:
|
||||
def send(self, request: bytes) -> bytes:
|
||||
def send(self, req: bytes) -> bytes:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@@ -374,7 +374,7 @@ class BaseMcuHid(BaseHid, multiprocessing.Process): # pylint: disable=too-many-
|
||||
self.__set_state_online(False)
|
||||
return False
|
||||
|
||||
def __process_request(self, conn: BasePhyConnection, request: bytes) -> bool: # pylint: disable=too-many-branches
|
||||
def __process_request(self, conn: BasePhyConnection, req: bytes) -> bool: # pylint: disable=too-many-branches
|
||||
logger = get_logger()
|
||||
error_messages: list[str] = []
|
||||
live_log_errors = False
|
||||
@@ -384,47 +384,47 @@ class BaseMcuHid(BaseHid, multiprocessing.Process): # pylint: disable=too-many-
|
||||
error_retval = False
|
||||
|
||||
while self.__gpio.is_powered() and common_retries and read_retries:
|
||||
response = (RESPONSE_LEGACY_OK if self.__noop else conn.send(request))
|
||||
resp = (RESPONSE_LEGACY_OK if self.__noop else conn.send(req))
|
||||
try:
|
||||
if len(response) < 4:
|
||||
if len(resp) < 4:
|
||||
read_retries -= 1
|
||||
raise _TempRequestError(f"No response from HID: request={request!r}")
|
||||
raise _TempRequestError(f"No response from HID: request={req!r}")
|
||||
|
||||
if not check_response(response):
|
||||
request = REQUEST_REPEAT
|
||||
if not check_response(resp):
|
||||
req = REQUEST_REPEAT
|
||||
raise _TempRequestError("Invalid response CRC; requesting response again ...")
|
||||
|
||||
code = response[1]
|
||||
code = resp[1]
|
||||
if code == 0x48: # Request timeout # pylint: disable=no-else-raise
|
||||
raise _TempRequestError(f"Got request timeout from HID: request={request!r}")
|
||||
raise _TempRequestError(f"Got request timeout from HID: request={req!r}")
|
||||
elif code == 0x40: # CRC Error
|
||||
raise _TempRequestError(f"Got CRC error of request from HID: request={request!r}")
|
||||
raise _TempRequestError(f"Got CRC error of request from HID: request={req!r}")
|
||||
elif code == 0x45: # Unknown command
|
||||
raise _PermRequestError(f"HID did not recognize the request={request!r}")
|
||||
raise _PermRequestError(f"HID did not recognize the request={req!r}")
|
||||
elif code == 0x24: # Rebooted?
|
||||
raise _PermRequestError("No previous command state inside HID, seems it was rebooted")
|
||||
elif code == 0x20: # Legacy done
|
||||
self.__set_state_online(True)
|
||||
return True
|
||||
elif code & 0x80: # Pong/Done with state
|
||||
self.__set_state_pong(response)
|
||||
self.__set_state_pong(resp)
|
||||
return True
|
||||
raise _TempRequestError(f"Invalid response from HID: request={request!r}, response=0x{response!r}")
|
||||
raise _TempRequestError(f"Invalid response from HID: request={req!r}, response=0x{resp!r}")
|
||||
|
||||
except _RequestError as err:
|
||||
except _RequestError as ex:
|
||||
common_retries -= 1
|
||||
|
||||
if live_log_errors:
|
||||
logger.error(err.msg)
|
||||
logger.error(ex.msg)
|
||||
else:
|
||||
error_messages.append(err.msg)
|
||||
error_messages.append(ex.msg)
|
||||
if len(error_messages) > self.__errors_threshold:
|
||||
for msg in error_messages:
|
||||
logger.error(msg)
|
||||
error_messages = []
|
||||
live_log_errors = True
|
||||
|
||||
if isinstance(err, _PermRequestError):
|
||||
if isinstance(ex, _PermRequestError):
|
||||
error_retval = True
|
||||
break
|
||||
|
||||
@@ -440,7 +440,7 @@ class BaseMcuHid(BaseHid, multiprocessing.Process): # pylint: disable=too-many-
|
||||
for msg in error_messages:
|
||||
logger.error(msg)
|
||||
if not (common_retries and read_retries):
|
||||
logger.error("Can't process HID request due many errors: %r", request)
|
||||
logger.error("Can't process HID request due many errors: %r", req)
|
||||
return error_retval
|
||||
|
||||
def __set_state_online(self, online: bool) -> None:
|
||||
@@ -449,11 +449,11 @@ class BaseMcuHid(BaseHid, multiprocessing.Process): # pylint: disable=too-many-
|
||||
def __set_state_busy(self, busy: bool) -> None:
|
||||
self.__state_flags.update(busy=int(busy))
|
||||
|
||||
def __set_state_pong(self, response: bytes) -> None:
|
||||
status = response[1] << 16
|
||||
if len(response) > 4:
|
||||
status |= (response[2] << 8) | response[3]
|
||||
reset_required = (1 if response[1] & 0b01000000 else 0)
|
||||
def __set_state_pong(self, resp: bytes) -> None:
|
||||
status = resp[1] << 16
|
||||
if len(resp) > 4:
|
||||
status |= (resp[2] << 8) | resp[3]
|
||||
reset_required = (1 if resp[1] & 0b01000000 else 0)
|
||||
self.__state_flags.update(online=1, busy=reset_required, status=status)
|
||||
if reset_required:
|
||||
if self.__reset_self:
|
||||
|
||||
@@ -47,12 +47,12 @@ class Gpio: # pylint: disable=too-many-instance-attributes
|
||||
self.__reset_inverted = reset_inverted
|
||||
self.__reset_delay = reset_delay
|
||||
|
||||
self.__line_request: (gpiod.LineRequest | None) = None
|
||||
self.__line_req: (gpiod.LineRequest | None) = None
|
||||
self.__last_power: (bool | None) = None
|
||||
|
||||
def __enter__(self) -> None:
|
||||
if self.__power_detect_pin >= 0 or self.__reset_pin >= 0:
|
||||
assert self.__line_request is None
|
||||
assert self.__line_req is None
|
||||
config: dict[int, gpiod.LineSettings] = {}
|
||||
if self.__power_detect_pin >= 0:
|
||||
config[self.__power_detect_pin] = gpiod.LineSettings(
|
||||
@@ -65,7 +65,7 @@ class Gpio: # pylint: disable=too-many-instance-attributes
|
||||
output_value=gpiod.line.Value(self.__reset_inverted),
|
||||
)
|
||||
assert len(config) > 0
|
||||
self.__line_request = gpiod.request_lines(
|
||||
self.__line_req = gpiod.request_lines(
|
||||
self.__device_path,
|
||||
consumer="kvmd::hid",
|
||||
config=config,
|
||||
@@ -78,18 +78,18 @@ class Gpio: # pylint: disable=too-many-instance-attributes
|
||||
_tb: types.TracebackType,
|
||||
) -> None:
|
||||
|
||||
if self.__line_request:
|
||||
if self.__line_req:
|
||||
try:
|
||||
self.__line_request.release()
|
||||
self.__line_req.release()
|
||||
except Exception:
|
||||
pass
|
||||
self.__last_power = None
|
||||
self.__line_request = None
|
||||
self.__line_req = None
|
||||
|
||||
def is_powered(self) -> bool:
|
||||
if self.__power_detect_pin >= 0:
|
||||
assert self.__line_request
|
||||
power = bool(self.__line_request.get_value(self.__power_detect_pin).value)
|
||||
assert self.__line_req
|
||||
power = bool(self.__line_req.get_value(self.__power_detect_pin).value)
|
||||
if power != self.__last_power:
|
||||
get_logger(0).info("HID power state changed: %s -> %s", self.__last_power, power)
|
||||
self.__last_power = power
|
||||
@@ -98,11 +98,11 @@ class Gpio: # pylint: disable=too-many-instance-attributes
|
||||
|
||||
def reset(self) -> None:
|
||||
if self.__reset_pin >= 0:
|
||||
assert self.__line_request
|
||||
assert self.__line_req
|
||||
try:
|
||||
self.__line_request.set_value(self.__reset_pin, gpiod.line.Value(not self.__reset_inverted))
|
||||
self.__line_req.set_value(self.__reset_pin, gpiod.line.Value(not self.__reset_inverted))
|
||||
time.sleep(self.__reset_delay)
|
||||
finally:
|
||||
self.__line_request.set_value(self.__reset_pin, gpiod.line.Value(self.__reset_inverted))
|
||||
self.__line_req.set_value(self.__reset_pin, gpiod.line.Value(self.__reset_inverted))
|
||||
time.sleep(1)
|
||||
get_logger(0).info("Reset HID performed")
|
||||
|
||||
@@ -184,17 +184,17 @@ class MouseWheelEvent(BaseEvent):
|
||||
|
||||
|
||||
# =====
|
||||
def check_response(response: bytes) -> bool:
|
||||
assert len(response) in (4, 8), response
|
||||
return (bitbang.make_crc16(response[:-2]) == struct.unpack(">H", response[-2:])[0])
|
||||
def check_response(resp: bytes) -> bool:
|
||||
assert len(resp) in (4, 8), resp
|
||||
return (bitbang.make_crc16(resp[:-2]) == struct.unpack(">H", resp[-2:])[0])
|
||||
|
||||
|
||||
def _make_request(command: bytes) -> bytes:
|
||||
assert len(command) == 5, command
|
||||
request = b"\x33" + command
|
||||
request += struct.pack(">H", bitbang.make_crc16(request))
|
||||
assert len(request) == 8, request
|
||||
return request
|
||||
def _make_request(cmd: bytes) -> bytes:
|
||||
assert len(cmd) == 5, cmd
|
||||
req = b"\x33" + cmd
|
||||
req += struct.pack(">H", bitbang.make_crc16(req))
|
||||
assert len(req) == 8, req
|
||||
return req
|
||||
|
||||
|
||||
# =====
|
||||
|
||||
@@ -182,8 +182,8 @@ class BtServer: # pylint: disable=too-many-instance-attributes
|
||||
self.__close_client("CTL", client, "ctl_sock")
|
||||
elif data == b"\x71":
|
||||
sock.send(b"\x00")
|
||||
except Exception as err:
|
||||
get_logger(0).exception("CTL socket error on %s: %s", client.addr, tools.efmt(err))
|
||||
except Exception as ex:
|
||||
get_logger(0).exception("CTL socket error on %s: %s", client.addr, tools.efmt(ex))
|
||||
self.__close_client("CTL", client, "ctl_sock")
|
||||
continue
|
||||
|
||||
@@ -196,8 +196,8 @@ class BtServer: # pylint: disable=too-many-instance-attributes
|
||||
self.__close_client("INT", client, "int_sock")
|
||||
elif data[:2] == b"\xA2\x01":
|
||||
self.__process_leds(data[2])
|
||||
except Exception as err:
|
||||
get_logger(0).exception("INT socket error on %s: %s", client.addr, tools.efmt(err))
|
||||
except Exception as ex:
|
||||
get_logger(0).exception("INT socket error on %s: %s", client.addr, tools.efmt(ex))
|
||||
self.__close_client("INT", client, "ctl_sock")
|
||||
|
||||
if qr in ready_read:
|
||||
@@ -279,8 +279,8 @@ class BtServer: # pylint: disable=too-many-instance-attributes
|
||||
assert client.int_sock is not None
|
||||
try:
|
||||
client.int_sock.send(report)
|
||||
except Exception as err:
|
||||
get_logger(0).info("Can't send %s report to %s: %s", name, client.addr, tools.efmt(err))
|
||||
except Exception as ex:
|
||||
get_logger(0).info("Can't send %s report to %s: %s", name, client.addr, tools.efmt(ex))
|
||||
self.__close_client_pair(client)
|
||||
|
||||
def __clear_modifiers(self) -> None:
|
||||
@@ -371,13 +371,13 @@ class BtServer: # pylint: disable=too-many-instance-attributes
|
||||
logger.info("Publishing ..." if public else "Unpublishing ...")
|
||||
try:
|
||||
self.__iface.set_public(public)
|
||||
except Exception as err:
|
||||
logger.error("Can't change public mode: %s", tools.efmt(err))
|
||||
except Exception as ex:
|
||||
logger.error("Can't change public mode: %s", tools.efmt(ex))
|
||||
|
||||
def __unpair_client(self, client: _BtClient) -> None:
|
||||
logger = get_logger(0)
|
||||
logger.info("Unpairing %s ...", client.addr)
|
||||
try:
|
||||
self.__iface.unpair(client.addr)
|
||||
except Exception as err:
|
||||
logger.error("Can't unpair %s: %s", client.addr, tools.efmt(err))
|
||||
except Exception as ex:
|
||||
logger.error("Can't unpair %s: %s", client.addr, tools.efmt(ex))
|
||||
|
||||
@@ -230,9 +230,9 @@ class Plugin(BaseHid, multiprocessing.Process): # pylint: disable=too-many-inst
|
||||
def __process_cmd(self, conn: ChipConnection, cmd: bytes) -> bool: # pylint: disable=too-many-branches
|
||||
try:
|
||||
led_byte = conn.xfer(cmd)
|
||||
except ChipResponseError as err:
|
||||
except ChipResponseError as ex:
|
||||
self.__set_state_online(False)
|
||||
get_logger(0).info(err)
|
||||
get_logger(0).error("Invalid chip response: %s", tools.efmt(ex))
|
||||
time.sleep(2)
|
||||
else:
|
||||
if led_byte >= 0:
|
||||
|
||||
@@ -192,13 +192,13 @@ class BaseDeviceProcess(multiprocessing.Process): # pylint: disable=too-many-in
|
||||
else:
|
||||
logger.error("HID-%s write() error: written (%s) != report length (%d)",
|
||||
self.__name, written, len(report))
|
||||
except Exception as err:
|
||||
if isinstance(err, OSError) and (
|
||||
except Exception as ex:
|
||||
if isinstance(ex, OSError) and (
|
||||
# https://github.com/raspberrypi/linux/commit/61b7f805dc2fd364e0df682de89227e94ce88e25
|
||||
err.errno == errno.EAGAIN # pylint: disable=no-member
|
||||
or err.errno == errno.ESHUTDOWN # pylint: disable=no-member
|
||||
ex.errno == errno.EAGAIN # pylint: disable=no-member
|
||||
or ex.errno == errno.ESHUTDOWN # pylint: disable=no-member
|
||||
):
|
||||
logger.debug("HID-%s busy/unplugged (write): %s", self.__name, tools.efmt(err))
|
||||
logger.debug("HID-%s busy/unplugged (write): %s", self.__name, tools.efmt(ex))
|
||||
else:
|
||||
logger.exception("Can't write report to HID-%s", self.__name)
|
||||
|
||||
@@ -216,16 +216,16 @@ class BaseDeviceProcess(multiprocessing.Process): # pylint: disable=too-many-in
|
||||
while read:
|
||||
try:
|
||||
read = bool(select.select([self.__fd], [], [], 0)[0])
|
||||
except Exception as err:
|
||||
logger.error("Can't select() for read HID-%s: %s", self.__name, tools.efmt(err))
|
||||
except Exception as ex:
|
||||
logger.error("Can't select() for read HID-%s: %s", self.__name, tools.efmt(ex))
|
||||
break
|
||||
|
||||
if read:
|
||||
try:
|
||||
report = os.read(self.__fd, self.__read_size)
|
||||
except Exception as err:
|
||||
if isinstance(err, OSError) and err.errno == errno.EAGAIN: # pylint: disable=no-member
|
||||
logger.debug("HID-%s busy/unplugged (read): %s", self.__name, tools.efmt(err))
|
||||
except Exception as ex:
|
||||
if isinstance(ex, OSError) and ex.errno == errno.EAGAIN: # pylint: disable=no-member
|
||||
logger.debug("HID-%s busy/unplugged (read): %s", self.__name, tools.efmt(ex))
|
||||
else:
|
||||
logger.exception("Can't read report from HID-%s", self.__name)
|
||||
else:
|
||||
@@ -255,9 +255,9 @@ class BaseDeviceProcess(multiprocessing.Process): # pylint: disable=too-many-in
|
||||
flags = os.O_NONBLOCK
|
||||
flags |= (os.O_RDWR if self.__read_size else os.O_WRONLY)
|
||||
self.__fd = os.open(self.__device_path, flags)
|
||||
except Exception as err:
|
||||
except Exception as ex:
|
||||
logger.error("Can't open HID-%s device %s: %s",
|
||||
self.__name, self.__device_path, tools.efmt(err))
|
||||
self.__name, self.__device_path, tools.efmt(ex))
|
||||
|
||||
if self.__fd >= 0:
|
||||
try:
|
||||
@@ -268,8 +268,8 @@ class BaseDeviceProcess(multiprocessing.Process): # pylint: disable=too-many-in
|
||||
else:
|
||||
# Если запись недоступна, то скорее всего устройство отключено
|
||||
logger.debug("HID-%s is busy/unplugged (write select)", self.__name)
|
||||
except Exception as err:
|
||||
logger.error("Can't select() for write HID-%s: %s", self.__name, tools.efmt(err))
|
||||
except Exception as ex:
|
||||
logger.error("Can't select() for write HID-%s: %s", self.__name, tools.efmt(ex))
|
||||
|
||||
self.__state_flags.update(online=False)
|
||||
return False
|
||||
|
||||
@@ -44,12 +44,12 @@ class _SerialPhyConnection(BasePhyConnection):
|
||||
def __init__(self, tty: serial.Serial) -> None:
|
||||
self.__tty = tty
|
||||
|
||||
def send(self, request: bytes) -> bytes:
|
||||
assert len(request) == 8
|
||||
assert request[0] == 0x33
|
||||
def send(self, req: bytes) -> bytes:
|
||||
assert len(req) == 8
|
||||
assert req[0] == 0x33
|
||||
if self.__tty.in_waiting:
|
||||
self.__tty.read_all()
|
||||
assert self.__tty.write(request) == 8
|
||||
assert self.__tty.write(req) == 8
|
||||
data = self.__tty.read(4)
|
||||
if len(data) == 4:
|
||||
if data[0] == 0x34: # New response protocol
|
||||
|
||||
@@ -57,9 +57,9 @@ class _SpiPhyConnection(BasePhyConnection):
|
||||
self.__xfer = xfer
|
||||
self.__read_timeout = read_timeout
|
||||
|
||||
def send(self, request: bytes) -> bytes:
|
||||
assert len(request) == 8
|
||||
assert request[0] == 0x33
|
||||
def send(self, req: bytes) -> bytes:
|
||||
assert len(req) == 8
|
||||
assert req[0] == 0x33
|
||||
|
||||
deadline_ts = time.monotonic() + self.__read_timeout
|
||||
dummy = b"\x00" * 10
|
||||
@@ -70,26 +70,26 @@ class _SpiPhyConnection(BasePhyConnection):
|
||||
get_logger(0).error("SPI timeout reached while garbage reading")
|
||||
return b""
|
||||
|
||||
self.__xfer(request)
|
||||
self.__xfer(req)
|
||||
|
||||
response: list[int] = []
|
||||
resp: list[int] = []
|
||||
deadline_ts = time.monotonic() + self.__read_timeout
|
||||
found = False
|
||||
while time.monotonic() < deadline_ts:
|
||||
for byte in self.__xfer(b"\x00" * (9 - len(response))):
|
||||
for byte in self.__xfer(b"\x00" * (9 - len(resp))):
|
||||
if not found:
|
||||
if byte == 0:
|
||||
continue
|
||||
found = True
|
||||
response.append(byte)
|
||||
if len(response) == 8:
|
||||
resp.append(byte)
|
||||
if len(resp) == 8:
|
||||
break
|
||||
if len(response) == 8:
|
||||
if len(resp) == 8:
|
||||
break
|
||||
else:
|
||||
get_logger(0).error("SPI timeout reached while responce waiting")
|
||||
return b""
|
||||
return bytes(response)
|
||||
return bytes(resp)
|
||||
|
||||
|
||||
class _SpiPhy(BasePhy): # pylint: disable=too-many-instance-attributes
|
||||
|
||||
Reference in New Issue
Block a user