mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2025-12-12 01:00:29 +08:00
switch: added ignore_hpd quirk for bad csi boards
This commit is contained in:
parent
02740aef37
commit
6a08fab818
@ -508,6 +508,7 @@ def _get_config_scheme() -> dict:
|
|||||||
"switch": {
|
"switch": {
|
||||||
"device": Option("/dev/kvmd-switch", type=valid_abs_path, unpack_as="device_path"),
|
"device": Option("/dev/kvmd-switch", type=valid_abs_path, unpack_as="device_path"),
|
||||||
"default_edid": Option("/etc/kvmd/switch-edid.hex", type=valid_abs_path, unpack_as="default_edid_path"),
|
"default_edid": Option("/etc/kvmd/switch-edid.hex", type=valid_abs_path, unpack_as="default_edid_path"),
|
||||||
|
"ignore_hpd_on_top": Option(False, type=valid_bool),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -84,11 +84,12 @@ class Switch: # pylint: disable=too-many-public-methods
|
|||||||
device_path: str,
|
device_path: str,
|
||||||
default_edid_path: str,
|
default_edid_path: str,
|
||||||
pst_unix_path: str,
|
pst_unix_path: str,
|
||||||
|
ignore_hpd_on_top: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
self.__default_edid_path = default_edid_path
|
self.__default_edid_path = default_edid_path
|
||||||
|
|
||||||
self.__chain = Chain(device_path)
|
self.__chain = Chain(device_path, ignore_hpd_on_top)
|
||||||
self.__cache = StateCache()
|
self.__cache = StateCache()
|
||||||
self.__storage = Storage(pst_unix_path)
|
self.__storage = Storage(pst_unix_path)
|
||||||
|
|
||||||
|
|||||||
@ -177,8 +177,14 @@ class UnitAtxLedsEvent(BaseEvent):
|
|||||||
|
|
||||||
# =====
|
# =====
|
||||||
class Chain: # pylint: disable=too-many-instance-attributes
|
class Chain: # pylint: disable=too-many-instance-attributes
|
||||||
def __init__(self, device_path: str) -> None:
|
def __init__(
|
||||||
|
self,
|
||||||
|
device_path: str,
|
||||||
|
ignore_hpd_on_top: bool,
|
||||||
|
) -> None:
|
||||||
|
|
||||||
self.__device = Device(device_path)
|
self.__device = Device(device_path)
|
||||||
|
self.__ignore_hpd_on_top = ignore_hpd_on_top
|
||||||
|
|
||||||
self.__actual = False
|
self.__actual = False
|
||||||
|
|
||||||
@ -293,6 +299,7 @@ class Chain: # pylint: disable=too-many-instance-attributes
|
|||||||
if self.__select():
|
if self.__select():
|
||||||
for resp in self.__device.read_all():
|
for resp in self.__device.read_all():
|
||||||
self.__update_units(resp)
|
self.__update_units(resp)
|
||||||
|
self.__adjust_quirks()
|
||||||
self.__adjust_start_port()
|
self.__adjust_start_port()
|
||||||
self.__finish_changing_request(resp)
|
self.__finish_changing_request(resp)
|
||||||
self.__consume_commands()
|
self.__consume_commands()
|
||||||
@ -364,6 +371,15 @@ class Chain: # pylint: disable=too-many-instance-attributes
|
|||||||
self.__units[resp.header.unit].atx_leds = resp.body
|
self.__units[resp.header.unit].atx_leds = resp.body
|
||||||
self.__queue_event(UnitAtxLedsEvent(resp.header.unit, resp.body))
|
self.__queue_event(UnitAtxLedsEvent(resp.header.unit, resp.body))
|
||||||
|
|
||||||
|
def __adjust_quirks(self) -> None:
|
||||||
|
for (unit, ctx) in enumerate(self.__units):
|
||||||
|
if ctx.state is not None and (ctx.state.version.sw_dev or ctx.state.version.sw >= 7):
|
||||||
|
ignore_hpd = (unit == 0 and self.__ignore_hpd_on_top)
|
||||||
|
if ctx.state.quirks.ignore_hpd != ignore_hpd:
|
||||||
|
get_logger().info("Applying quirk ignore_hpd=%s to [%d] ...",
|
||||||
|
ignore_hpd, unit)
|
||||||
|
self.__device.request_set_quirks(unit, ignore_hpd)
|
||||||
|
|
||||||
def __adjust_start_port(self) -> None:
|
def __adjust_start_port(self) -> None:
|
||||||
if self.__active_port < 0:
|
if self.__active_port < 0:
|
||||||
for (unit, ctx) in enumerate(self.__units):
|
for (unit, ctx) in enumerate(self.__units):
|
||||||
|
|||||||
@ -42,6 +42,7 @@ from .proto import BodyAtxClick
|
|||||||
from .proto import BodySetEdid
|
from .proto import BodySetEdid
|
||||||
from .proto import BodyClearEdid
|
from .proto import BodyClearEdid
|
||||||
from .proto import BodySetColors
|
from .proto import BodySetColors
|
||||||
|
from .proto import BodySetQuirks
|
||||||
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
@ -166,6 +167,9 @@ class Device:
|
|||||||
def request_set_colors(self, unit: int, ch: int, colors: Colors) -> int:
|
def request_set_colors(self, unit: int, ch: int, colors: Colors) -> int:
|
||||||
return self.__send_request(Header.SET_COLORS, unit, BodySetColors(ch, colors))
|
return self.__send_request(Header.SET_COLORS, unit, BodySetColors(ch, colors))
|
||||||
|
|
||||||
|
def request_set_quirks(self, unit: int, ignore_hpd: bool) -> int:
|
||||||
|
return self.__send_request(Header.SET_QUIRKS, unit, BodySetQuirks(ignore_hpd))
|
||||||
|
|
||||||
def __send_request(self, op: int, unit: int, body: (Packable | None)) -> int:
|
def __send_request(self, op: int, unit: int, body: (Packable | None)) -> int:
|
||||||
assert self.__tty is not None
|
assert self.__tty is not None
|
||||||
req = Request(Header(
|
req = Request(Header(
|
||||||
|
|||||||
@ -60,6 +60,7 @@ class Header(Packable, Unpackable):
|
|||||||
SET_EDID = 9
|
SET_EDID = 9
|
||||||
CLEAR_EDID = 10
|
CLEAR_EDID = 10
|
||||||
SET_COLORS = 12
|
SET_COLORS = 12
|
||||||
|
SET_QUIRKS = 13
|
||||||
|
|
||||||
__struct = struct.Struct("<BHBB")
|
__struct = struct.Struct("<BHBB")
|
||||||
|
|
||||||
@ -89,6 +90,13 @@ class Nak(Unpackable):
|
|||||||
return Nak(*cls.__struct.unpack_from(data, offset=offset))
|
return Nak(*cls.__struct.unpack_from(data, offset=offset))
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass(frozen=True)
|
||||||
|
class UnitVersion:
|
||||||
|
hw: int
|
||||||
|
sw: int
|
||||||
|
sw_dev: bool
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(frozen=True)
|
@dataclasses.dataclass(frozen=True)
|
||||||
class UnitFlags:
|
class UnitFlags:
|
||||||
changing_busy: bool
|
changing_busy: bool
|
||||||
@ -97,10 +105,14 @@ class UnitFlags:
|
|||||||
has_hpd: bool
|
has_hpd: bool
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass(frozen=True)
|
||||||
|
class UnitQuirks:
|
||||||
|
ignore_hpd: bool
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(frozen=True)
|
@dataclasses.dataclass(frozen=True)
|
||||||
class UnitState(Unpackable): # pylint: disable=too-many-instance-attributes
|
class UnitState(Unpackable): # pylint: disable=too-many-instance-attributes
|
||||||
sw_version: int
|
version: UnitVersion
|
||||||
hw_version: int
|
|
||||||
flags: UnitFlags
|
flags: UnitFlags
|
||||||
ch: int
|
ch: int
|
||||||
beacons: tuple[bool, bool, bool, bool, bool, bool]
|
beacons: tuple[bool, bool, bool, bool, bool, bool]
|
||||||
@ -111,8 +123,9 @@ class UnitState(Unpackable): # pylint: disable=too-many-instance-attributes
|
|||||||
video_crc: tuple[int, int, int, int]
|
video_crc: tuple[int, int, int, int]
|
||||||
usb_5v_sens: tuple[bool, bool, bool, bool]
|
usb_5v_sens: tuple[bool, bool, bool, bool]
|
||||||
atx_busy: tuple[bool, bool, bool, bool]
|
atx_busy: tuple[bool, bool, bool, bool]
|
||||||
|
quirks: UnitQuirks
|
||||||
|
|
||||||
__struct = struct.Struct("<HHHBBHHHHHHBBBHHHHBxB30x")
|
__struct = struct.Struct("<HHHBBHHHHHHBBBHHHHBxBB29x")
|
||||||
|
|
||||||
def compare_edid(self, ch: int, edid: Optional["Edid"]) -> bool:
|
def compare_edid(self, ch: int, edid: Optional["Edid"]) -> bool:
|
||||||
if edid is None:
|
if edid is None:
|
||||||
@ -129,11 +142,14 @@ class UnitState(Unpackable): # pylint: disable=too-many-instance-attributes
|
|||||||
sw_version, hw_version, flags, ch,
|
sw_version, hw_version, flags, ch,
|
||||||
beacons, nc0, nc1, nc2, nc3, nc4, nc5,
|
beacons, nc0, nc1, nc2, nc3, nc4, nc5,
|
||||||
video_5v_sens, video_hpd, video_edid, vc0, vc1, vc2, vc3,
|
video_5v_sens, video_hpd, video_edid, vc0, vc1, vc2, vc3,
|
||||||
usb_5v_sens, atx_busy,
|
usb_5v_sens, atx_busy, quirks,
|
||||||
) = cls.__struct.unpack_from(data, offset=offset)
|
) = cls.__struct.unpack_from(data, offset=offset)
|
||||||
return UnitState(
|
return UnitState(
|
||||||
sw_version,
|
version=UnitVersion(
|
||||||
hw_version,
|
hw=hw_version,
|
||||||
|
sw=(sw_version & 0x7FFF),
|
||||||
|
sw_dev=bool(sw_version & 0x8000),
|
||||||
|
),
|
||||||
flags=UnitFlags(
|
flags=UnitFlags(
|
||||||
changing_busy=bool(flags & 0x80),
|
changing_busy=bool(flags & 0x80),
|
||||||
flashing_busy=bool(flags & 0x40),
|
flashing_busy=bool(flags & 0x40),
|
||||||
@ -149,6 +165,7 @@ class UnitState(Unpackable): # pylint: disable=too-many-instance-attributes
|
|||||||
video_crc=(vc0, vc1, vc2, vc3),
|
video_crc=(vc0, vc1, vc2, vc3),
|
||||||
usb_5v_sens=cls.__make_flags4(usb_5v_sens),
|
usb_5v_sens=cls.__make_flags4(usb_5v_sens),
|
||||||
atx_busy=cls.__make_flags4(atx_busy),
|
atx_busy=cls.__make_flags4(atx_busy),
|
||||||
|
quirks=UnitQuirks(ignore_hpd=bool(quirks & 0x01)),
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -265,6 +282,14 @@ class BodySetColors(Packable):
|
|||||||
return self.ch.to_bytes() + self.colors.pack()
|
return self.ch.to_bytes() + self.colors.pack()
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass(frozen=True)
|
||||||
|
class BodySetQuirks(Packable):
|
||||||
|
ignore_hpd: bool
|
||||||
|
|
||||||
|
def pack(self) -> bytes:
|
||||||
|
return self.ignore_hpd.to_bytes()
|
||||||
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
@dataclasses.dataclass(frozen=True)
|
@dataclasses.dataclass(frozen=True)
|
||||||
class Request:
|
class Request:
|
||||||
|
|||||||
@ -49,7 +49,7 @@ class _UnitInfo:
|
|||||||
|
|
||||||
# =====
|
# =====
|
||||||
class StateCache: # pylint: disable=too-many-instance-attributes
|
class StateCache: # pylint: disable=too-many-instance-attributes
|
||||||
__FW_VERSION = 6
|
__FW_VERSION = 7
|
||||||
|
|
||||||
__FULL = 0xFFFF
|
__FULL = 0xFFFF
|
||||||
__SUMMARY = 0x01
|
__SUMMARY = 0x01
|
||||||
@ -195,7 +195,10 @@ class StateCache: # pylint: disable=too-many-instance-attributes
|
|||||||
assert ui.state is not None
|
assert ui.state is not None
|
||||||
assert ui.atx_leds is not None
|
assert ui.atx_leds is not None
|
||||||
if x_model:
|
if x_model:
|
||||||
state["model"]["units"].append({"firmware": {"version": ui.state.sw_version}})
|
state["model"]["units"].append({"firmware": {
|
||||||
|
"version": ui.state.version.sw,
|
||||||
|
"devbuild": ui.state.version.sw_dev,
|
||||||
|
}})
|
||||||
if x_video:
|
if x_video:
|
||||||
state["video"]["links"].extend(ui.state.video_5v_sens[:4])
|
state["video"]["links"].extend(ui.state.video_5v_sens[:4])
|
||||||
if x_usb:
|
if x_usb:
|
||||||
|
|||||||
Binary file not shown.
@ -408,7 +408,8 @@ export function Switch() {
|
|||||||
$("switch-chain").innerHTML = content;
|
$("switch-chain").innerHTML = content;
|
||||||
|
|
||||||
if (model.units.length > 0) {
|
if (model.units.length > 0) {
|
||||||
tools.hidden.setVisible($("switch-message-update"), (model.firmware.version > model.units[0].firmware.version));
|
let fw = model.units[0].firmware;
|
||||||
|
tools.hidden.setVisible($("switch-message-update"), (fw.devbuild || fw.version < model.firmware.version));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let unit = 0; unit < model.units.length; ++unit) {
|
for (let unit = 0; unit < model.units.length; ++unit) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user