From 6a08fab8180155da2e0725c4992ae0ff3dc2834f Mon Sep 17 00:00:00 2001 From: Maxim Devaev Date: Sun, 16 Feb 2025 01:00:38 +0200 Subject: [PATCH] switch: added ignore_hpd quirk for bad csi boards --- kvmd/apps/__init__.py | 5 ++-- kvmd/apps/kvmd/switch/__init__.py | 3 ++- kvmd/apps/kvmd/switch/chain.py | 18 ++++++++++++++- kvmd/apps/kvmd/switch/device.py | 4 ++++ kvmd/apps/kvmd/switch/proto.py | 37 +++++++++++++++++++++++++----- kvmd/apps/kvmd/switch/state.py | 7 ++++-- switch/switch.uf2 | Bin 192512 -> 195584 bytes web/share/js/kvm/switch.js | 3 ++- 8 files changed, 64 insertions(+), 13 deletions(-) diff --git a/kvmd/apps/__init__.py b/kvmd/apps/__init__.py index e48079a5..ef258044 100644 --- a/kvmd/apps/__init__.py +++ b/kvmd/apps/__init__.py @@ -506,8 +506,9 @@ def _get_config_scheme() -> dict: }, "switch": { - "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"), + "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"), + "ignore_hpd_on_top": Option(False, type=valid_bool), }, }, diff --git a/kvmd/apps/kvmd/switch/__init__.py b/kvmd/apps/kvmd/switch/__init__.py index 49bfbd7d..f0cc98f2 100644 --- a/kvmd/apps/kvmd/switch/__init__.py +++ b/kvmd/apps/kvmd/switch/__init__.py @@ -84,11 +84,12 @@ class Switch: # pylint: disable=too-many-public-methods device_path: str, default_edid_path: str, pst_unix_path: str, + ignore_hpd_on_top: bool, ) -> None: 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.__storage = Storage(pst_unix_path) diff --git a/kvmd/apps/kvmd/switch/chain.py b/kvmd/apps/kvmd/switch/chain.py index 8e4d94eb..7137f5b9 100644 --- a/kvmd/apps/kvmd/switch/chain.py +++ b/kvmd/apps/kvmd/switch/chain.py @@ -177,8 +177,14 @@ class UnitAtxLedsEvent(BaseEvent): # ===== 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.__ignore_hpd_on_top = ignore_hpd_on_top self.__actual = False @@ -293,6 +299,7 @@ class Chain: # pylint: disable=too-many-instance-attributes if self.__select(): for resp in self.__device.read_all(): self.__update_units(resp) + self.__adjust_quirks() self.__adjust_start_port() self.__finish_changing_request(resp) 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.__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: if self.__active_port < 0: for (unit, ctx) in enumerate(self.__units): diff --git a/kvmd/apps/kvmd/switch/device.py b/kvmd/apps/kvmd/switch/device.py index b56cc406..a057a50d 100644 --- a/kvmd/apps/kvmd/switch/device.py +++ b/kvmd/apps/kvmd/switch/device.py @@ -42,6 +42,7 @@ from .proto import BodyAtxClick from .proto import BodySetEdid from .proto import BodyClearEdid 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: 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: assert self.__tty is not None req = Request(Header( diff --git a/kvmd/apps/kvmd/switch/proto.py b/kvmd/apps/kvmd/switch/proto.py index 43da118f..2081a4b6 100644 --- a/kvmd/apps/kvmd/switch/proto.py +++ b/kvmd/apps/kvmd/switch/proto.py @@ -60,6 +60,7 @@ class Header(Packable, Unpackable): SET_EDID = 9 CLEAR_EDID = 10 SET_COLORS = 12 + SET_QUIRKS = 13 __struct = struct.Struct(" bool: if edid is None: @@ -129,11 +142,14 @@ class UnitState(Unpackable): # pylint: disable=too-many-instance-attributes sw_version, hw_version, flags, ch, beacons, nc0, nc1, nc2, nc3, nc4, nc5, 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) return UnitState( - sw_version, - hw_version, + version=UnitVersion( + hw=hw_version, + sw=(sw_version & 0x7FFF), + sw_dev=bool(sw_version & 0x8000), + ), flags=UnitFlags( changing_busy=bool(flags & 0x80), flashing_busy=bool(flags & 0x40), @@ -149,6 +165,7 @@ class UnitState(Unpackable): # pylint: disable=too-many-instance-attributes video_crc=(vc0, vc1, vc2, vc3), usb_5v_sens=cls.__make_flags4(usb_5v_sens), atx_busy=cls.__make_flags4(atx_busy), + quirks=UnitQuirks(ignore_hpd=bool(quirks & 0x01)), ) @classmethod @@ -265,6 +282,14 @@ class BodySetColors(Packable): 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) class Request: diff --git a/kvmd/apps/kvmd/switch/state.py b/kvmd/apps/kvmd/switch/state.py index 5b06db0a..84f01cfd 100644 --- a/kvmd/apps/kvmd/switch/state.py +++ b/kvmd/apps/kvmd/switch/state.py @@ -49,7 +49,7 @@ class _UnitInfo: # ===== class StateCache: # pylint: disable=too-many-instance-attributes - __FW_VERSION = 6 + __FW_VERSION = 7 __FULL = 0xFFFF __SUMMARY = 0x01 @@ -195,7 +195,10 @@ class StateCache: # pylint: disable=too-many-instance-attributes assert ui.state is not None assert ui.atx_leds is not None 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: state["video"]["links"].extend(ui.state.video_5v_sens[:4]) if x_usb: diff --git a/switch/switch.uf2 b/switch/switch.uf2 index c6581ab91f1673ffe79a59b8ad5b662e4d2656cf..e5a1725e97622f8bca75a37282bef511a737b468 100644 GIT binary patch delta 29538 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 K<-`@Q1pPn!KHF>n delta 27557 zcmch=2~-rv_CH?L%nZvgI5G&sW_o52QPiLqgSd@=EikBvXk3UHK$Brff(ts}0xn6^ zY-$@D)Ff*1-c!(opysL3M197XJd-z=O{4MQ5^>4WFUbqT49xs*PfyPje)IjG-#Nc? ze&!V2J$37I@2$FZtLj#Dr{1otZ&z;CV(WX+Zj7yLH1%)Au3W4>ntRAa#dv;^jj1~d zznnsdZW)T`eao>LAsH8KIz`P&@o&6Ux-{h<@#_NL>Sz zC;x`jkIh0zfeP}Q51D8DJ{GHm`{&~VDA_pizEHpS^-#E%!|&G?{vKf2x19Y(rl)Mf z4>@H0ai$d`G|T-)gjFy8DHi)!klENmiiM% z8UAF}pqrQ1)=aDkr$RCn>^y~GhKz4^CD*uUU|Dszo_jA=h| zVyYaaT02@A7?g}``PV1c1U!r`KYYDDVFA)3q)Xfv%I|Tdp~U?%eqv9nsg-S0Xa>Dw zinbaJIT=c0Oy&VotW}eFAUE7vfHaxSxqYoNeNIM*QIokp7qioi8kP>U3pF34OAFsJ zedCuKgHWtYo2l76Yg54XZ#T&}-M|J@%!ifE36ZTv#Jnfoz!xTR*-+y&N@MlSggss-1?MB zxh2l}q$zZp7XGR>$5|Je!nQ@jU#&jQy1=B~wjeLoN~1no^eIT!mks6HdK3mtgQ33N ztZ2YH&DFD+x9Wp-nwQrr*;J7hTK>bup_)tzgD*6 zt>qZ=2H>@n}HHZQ-qJY;9+j<;r}8H zFT|-g3j4xc1p7-!ygroQ*fU9&f@HkB=cyL{#0N|(v!B@w#5^~bbIDCwM}6|1qR>L?U^wEHA8uvb&9Nycr6f6rZNecRJy-*(7&Z8u87 zZJ7Vq?j9ywGrCwlOgrS&?$nw=2#-lYso-A9yFX@HJ9N;&Q8Kn+zSaJa@BV;YYWavD zvE_q^mXBwzr^T}QYFXV*dt`PfZ|n)?nXZUDC5p(Q5ZXecQ2rfPxGC1sVClM$|^{6S|X)4a&U^tWy|ZO@IhhFfE)m`uk4qkfxdSw^gNUPg>@E2uvY#bj>r_`EG1 zUnf)p=j=;q*s$;rtz`P52dvkR06+M0?gtCl)p|XyVfW~xhUn;7o7OVp7ksnHRl4#| z9bdG^&s}UiUMe`g$NY}ZTKaVE(>c%liQ_BxI=(WW*I=hE~>W{qwm+^u6a zFlXRy)?9N=!CVLX>ZpgLHq?ZOZ5TqdA!|#C2oXiGwOUJ9J|(8^a%-+>bV-ag$K)v1 z!r!CCvDO&<~}&KK(91kstkB!lW~LgU5oI`2rkmKbU4!NN2(eQW2TjqG#!SgK}$q@N~K)Gw6KkG(ch zn=}sWugc^q)g}Jf&?}B}U$>t0Sl~R;0?oO_ImLfsfscDFu*hqHpSRZQ#(@RSgh98b z#64WF#1}pGH+^nBvx%9JGaUxtjqH{1SoXlE$ljI~Das%1_pQPpdZl$t$yig2KHfUk z)KeU79b-CH91nk2dF*aX@o2ES(I&e&-g?rUHbu0*Z@WbMb5u6hJIl-KMH`#Ph*mX& zxewNryxhdpR@PYVElRIUvkYGAsMv2VUwgdbSoxj#=E2q0iu8(#<*^}6)y-b}8&f`! zX@+6cQD!MT1~yk)hEwl?wcRUBhdVo1-f^(NJDy)e`{Qm)mLfSY-?$_bEJo0mbH-Ad zO0m7di1zy5#;i9?Z}zg8U0$2nN!U!I$7UM6Hq$`Z%y!Z%MGtu)d)xxufNwTE4>mzs z#6Fl8iPNz;p1F@?6MZC`_@;GP&hp&V?8N?>pv7JrkgV_VKB6{#2yGU5?c+SyM;c)t zvpkctL(HtXADOJrRf5gK>_C51J1w26Dz@g2IIitmwZ}TWDo}r>3h5O(YEkB*0RE8M-C65A z#r(OEO^h6v@@H;IaA3j&s032bP<+YVIm2nL2}r`1-JMbsvMRkYP8!vwIvb|^1I5PN z*Y5O83EZ8NoUAP=rr^aM3^N3GXQ~q!0{DSln@pQ}ndSzsX}&<1=5rp?T<Y&w*~$-*OsporML$Rqrs~M3GUU2Je(zU z_iLNH*@J5|ndP4B!9`vbN-Amxdvlwh@V!++;U-Vv?_0;4R+YqC$ANtde|x~b$AWze ze^(Wcof2zJLSu@@fUQSc>69)r(kb~s_c4pYu-`noBDsEl^>pTg%Derlo9mS!IZX1h zvSrGUiOe(0M}@qzT&$e|es?>cX@>0NtK)1Ldpk%kN||(-Ash}|IdKe8RntaGw?-s=l!m~PZ?%K!;tOF4Z)PrlqduM!cbz@2vdQ57esSBLu0+{i|!(U;<9aCHil~-!&g7FsVPMV87Bd(G^ z(&MO97zC3^t`|(^gG#|H5xoN=MoG|MX zhT7)kv;jt6^U+5u?k&5!JPGD}UEnBZGh@nY%aRMz4M#n$QXFB^%er8+6~|oBf%Z-H zb@xcIH6w}EY+#ONO=PBxQC5{$Vfo~l6V9!Y8U9%{(-5}Es2_yvS|$G^EPRD^!HsTr z=YG3R1up>Xwfmwtb`+V#~=lvq1aMC}B7#4_0z)*5PW)a7C+^`*j4+RN58n^h zhMavcKXJkODYg!#L(sR#Kv6TyRpxj)vNT~@RWiReX5}&%m?ATGKv#*({0<^R7vU)u z_s^_{?iFkO1E#ihFnz7_%v)B2Uyrq}C|+fXx2}SD%PNm|r&F9}B_G}G_36;P22EJo zRq;V(+1g{!zXny;RII2h12=zv(cNm&$HUxrnXsZ#hTL72ynGI$f&Qg4fLr(a{o#JU zf5&{hJgovedUb92&xPe4k8XzZrOyuGE1gIefPzrN4Q^6sN{DiN z1&NGu%!Y`^%nTSAyT`@_{o*KINv{m1SbBVd@FN_q&aNJo zADa|ZM~FaGIoS5}xS(Q3aUER;VtM1EgX2V5;s{xAX6b7EYHG{%)kz3%*|QpLk?AmB zz%Cg-ux`9VG4x=YV8c7vRO{KIacJ%!ekLpZ*nTeO0)Jtk=V_ivwK zBA|BoBSL_CDg^b~j~r_W;v2gc&`5{)4;+ZU>ki=ObYcGAZi+YcTsB?yIX1ktUjMC0 zHxL%znXvl)n(%F3dVJfLUf*_+@NJFEzf88=24-gs#d=raULPl^&Z^RhQPyni&!z{3 z=?XWU%8_mRdecXF^4AP2Zg}T?B`_=8>zNhaU=JGOllA(&p4s7*)uJqvkp~YjT2H)J z$xnfmH{Q{&p&SC!(VLqfE-lOlWIIgEV2Dc}V9M7jb~M)yhUj$g&hqM@9TDvHjM&V1 zOi7jy2c1zBub<(&*KScZsCI@n-iJl^o#kN-eRhZeA9dqBPqg}OVR(b!iZl?pzQaz+ z8X)R4F5W-4DbE^N_jC_Rim(krM!gXn$R+z^(|?G-3uRWA7oPK;;NENNhpyWwy1JZ157u<>?USspzUjS zf*gcMru>JH_90qa;B^&N+e7q>9Z(6U}zU76)P-w|@xRK7ZQf0QbPGLYC#U?}Hbce|c z|2_Du3}#-2#*Fwk?T8NGDHr0mIVnEFm6Z2ZjVw8$ZD5`Oh8(30@f&(DU*ALVKRPhD z^T(XR@4vNCybWf0YkRsoWHjc#u*+zQpX3tm^V~ASTZ^uB2m)^?1BqYh?gyib5~X-F z?d+1o*x|?o9XV))Q(s{emx|RJG_Yp~-n{*RxV5ldu^IA()*1=1ZeeZi2{OWO>LX#a zg8#zl>!^CM#r04(zPWp4u9lkC%|4$ylKQTPJ&~JIddwN1qoCkWxCX#=kW-Np2oCcg zJO{zE4z9s)jd!X~?tUI48-&j~U_0$Y%t2zn8oU`AQ3d@Tb0bh2uC0o{I{C+Wf z>IHpxP6`U)gVW22m;lA=P(gWH3|(^4~hyWqD~-frD+y(^DTh*st>PSbC}+ z(`@F{K@x%{K}1L(5ZKD83FBw>AOlJYZgc6v8aB#9_<7KeQQOb$F2hbaW|x~%Q0(K& zrWB!D+GVC&@Hd2?)`J^E_>i6u{;eMNi>U=Hoj+Dhd44?E9m3D*$z@KpihOejCsCPS zuRPu@6s-oTFt#&)5K9;2351-}L}|RigT!6}7SM{r6S4ZRk=5Vl z*o(aIFxy=i#3s$k^68x<(k1nxn>8Lsv(2-rS$eh)kyRBC#-B1ff~}vuo6VoCg=-LN zoIAt^Iaq`o+zWEmf!_bu;+_rv-Etg`j7e4AJPkS zej*;gvh#=IQ1;{b1{}}co&TtsE-NkzfKd?HUTRnH4i}qZ_VN=pO6L+vRGJU7bjc9v zVFx?4L@Qrw4~+A;Hr9bP{fCKK3?mqZ@T=`OE-fyEe~4XP@(AVbVyhNt!wc;7Od6Qv zRLC?k!Tc|7_EO0x>I*Sf=gp1x=6>jA(-(}8Dl6(?k&X` zr4$p5T4{ld@;o6l$vH}?2#r{H1W|YlyQMsp-CdqHGTk*GCz!w9<1#q(JLUV#_svEI z`krnp=zj=$VRP}m)D@XY#bw366~zPweI?s9H;|<()5A~q+_wJ3nhElbK!Z>~gFk{O zjZdirL$W~3WH^K2L8oFZ9*&D3SZ9UfdTa4V(dm`nGj@A@V$s+UpXe)44|XDM0sSKUh3^h`~eK zbfJ)j_Gi6z85+@dkcecgG&7!d;m@L^0ho*xlnoR%Y_L(Efiu}%Za z#10qM1=2G9CR`P8{kKaFf79G-!^-~PrT)IMjHOqPioE2iH%w5>ldUNEpjc}{2|Ji5 zQ=_N;1RpEp}$AxnfpSVm+{Ns3J65OA5vCpp_AKeXug&h*PM0ue_ z&Kub8R}YH0=+Idjo zL-zLi1nN^4yS08ima}d3)6}}*nS~H!G+pcyQzhqX!4t3bcw)}Eg3{2U@Z$;L-?H4W zXfjb-Q@fm>>0)cw(o~j<-L-aofSgCHVg1CQfA`!hdocrD_H~pABFY2;g{@qlMIGy5 zTh}L1Z}+fQ*Jt%l6=p%;{P;%@EmVOJy%G*j2~}}xB0K*1VLm{k2x#mD_`I2V!Onj1 zJdEWV5|T{zAkz&L9=lV!yf}VQKns5|AoDhGumM^EOk&Wf0HeS`!emuz$w6mB299Lk z-H;lyu0@ulzoaom~XN#0mvW;Ga*A%FoRGqL4nyaCMf$a#j;e~6vn^n zURWH^l5(Sa=YCwK`}Prr8HR>zuwK7Uz!>gmbJE~ZEbDDt7IbWbOb46vd2xS`?c|#DN@0RnkoJyoyhd8Y7Td~p|s6<|R|Rcnmd-P!Fz23eD)I$sCJowniB;HF^S|@`CM2+#n)rnnBnexg?(!4fVyKYIscJEiTXoG32#v}#%H4~ z0k2V9FrVNP;S)PH6nItOeyVHXB4|{|)#vsI2^~nzAgY73f z9vj%!VYx3JOgRq|cQn#}Fh!VIyWI%k-S9U9_fr=_W*Vd*NJdD)5hRx0=BYQqvy5ZJ zdSi%s3+8DDPAX|bAQobGGQ;82UN$)U7acORFJojIg{CuBOBnxK7rS=b$cWsYxlCys z+BzH!1~O`FFn_m;{cIa84*})X>@VBmBNn;iJ*RNO_y{}J$9hiTu=Msw#jPGWf3J%j zyIm`r;#Qg@(~X@hN;R2~N?6gUcpj{AdqkbExUqQEBJ~$kt@Nnr56oQ5+t^~T)+M9M zAA+}O>H62S6|mAkm;c_5+Tw0}J~h?aCmCH*+(7!hvp$=$8P{v;(R$`UmKx3~9=~p8 zur4#so!Y>h&HdOUx8jt?jmhk9+lR748fezopp|5<%NAwMCS+DLY3h-VGE9e=)fHD} z9BTX9^}m=#SQ{8@n8*YeUo3nJynL*MN~UakV0}9Vs$*i;?kP&N8w>_*NkT#Ve%Bi& zG+?L4UR8Xqn=<4w8nYs`k!dvTfFx)8w9kDU4CHKs8o$hb-C!`UaN$Q%tv|IkXZ&lV#j#YehRtvEFmd~}x`8R~QEwR0w>nQP2-PzxxzxNY^6WTB=mz16-FW{sN} z_?x(exjAdav_l#3Hl%Nw)tV7)6II^g59t2Zx`Qz>=~jqnwW7fT+hoIXZHF=j+mJ4w zad#$l2f`tjZ2%*G6pwO0+MabN<9b`5ej6h_%ZGj2HrV=9j>dQe_DHV;E31Ngg*veA zP(~nhig`6Cxo?{=e;e5i*mVHzaEjmp)XiA}xO~`qZI?PQ5b3*TKy2-P2Tl&PQOOZD z)0ABuvg9i^tdl|R_ppt8bJjmP^deo_6bglu%^H`Dw>+GKwupX+^+kGf2`dQVKkFIhv40i+vmo(5CQ|0bl?G!5MJtsB@Z5<139hVzDRcP%L^CEK+3}NimU38w% zjp82hyO1on9}B4+)>Iz@AXZ>}=m zB=!RnQ3Dg1T$B8t^3$bEv_%09&Sb-exfwGiPRhR0+Q08}jMnspc{lMNXW#(AGmMo1K2f@c3=zy?;r-{*J+(A!CvbsAP9TZfY zj9=syD$dtQZifpd;FLx13qe>x(8wuxOPJVIJ)HuUlXZEb{&|G{U;*7K$pSzNCA1gP z(N`GNv^!8B?L3=xA^#dIvJ-5ez8MIRjIJ z`0;Kz3QQVp%Z7&d-64Z@v=I1y6as7bH5!~y5MSIq#^ZeD?6|$Y=>@CWp&TNOeP2Sk z%dWvwl_^Q)=d-3-soo6?;WN1D-a%Vv8VPX)dhM{o4eoc5TZho(vrgM zU|d4*@Bm!@>~vDZD5#_(h+fwM%Rq>!$@u;~g4LIK?zKIF2PpO2hxgPO>hyIw#0vS) zF2X-H34bMwfc>Y6?KKsClhhdmCtW%`MHTE5Z^z?mcGcTs@MQMb+fT9l+X^=Euih!Z z>+u7mGD6=F+DICH2McWl;yu?A%wu-ZU;EXWU6>Aml7G2dpw8`9c=CT~!w?@sBlx-91FG(Jc+P}@uoaNhAYd?m##Ijv zIvj7#m^blKs~Ut8euqdW`>%bz$eSi#tfzdUp4gTqtt^<|;bJc|6|zN5gEeU`0kE^D zwS$6f12VP6b&vE(-FJT`)Fs?5R zk+=j~1%vg7z8nv8C${;(LWrj{12d)9so)?B1h|5LbC(;=K<=a zUQqb8ApSR4xrj5S?LI7FqAv*5@&J}3R52hu&wd4XW^aMfn8Q(NB%i+dES_kNA&2)HIZ$~s#0B9r~`p;D(ZSvIz?G(=jw zZ4)(19N+x5UTKjuuD=gJz2evk3&z zK7u_iKmdstEpTQ>93SrinJqrn9^dOZf>I1{yvsIahAd^_V$TU5~D=# z>Sr#&NY5PAtqpGz7n$Z-kesIPas+u<4k?^MM>lFY~kzukd!VGO(YT$2y- z2@&!M0&-pXr@<_J-fy*Lk;Y8W^t~8hW$DknG^hRTal5$w1WRA=7cLPCmk@<@g^}4T z{e_>VRHP{-Xuh>&8(7+Qf=V09UbBt&$-6)#T|khIxDLT}`l1hxReeVI=czU=JMybL zK7c1hfF}t6O{OuIrN8k4eC}5!Xq3>%m%3R4zRY&vh$xF#*g_N@1uGqv{*K^&(Qoie zi%~L5U-e~1m5Tu71i%dDW(iAQ^V3v_G!+ERj!Xjt+S>gz-XqYJ1kFV_p~=!WHdFQt zw)IB2sPJXKGV-lgz*27cF`g0mJVRhyZJz<_>)U>sXGNN42^zIQ*2vO#y8S)8T{%MX zcmWE{*L8-V+yLV@MU&y>l22`CId=S(^71W>t6mjk1}EfEN4Jml;(pBE!to z=ao+vVrco_d!)n4QOiV{WdsefO*gXiAAX$WBF%Dw=FChv7=Yb}!>V|{AaH7fWod^O z;6Hxx-@KjydUgAeYenQ*0$Esku(ZohvqGdjvjeRt%%I@b*wc|%Pn)2sH ztr8Jd5eNavi8hXw5k#v+qSXY^6;);yM=KIIcG5T>#?(y8qU!XID)!5i5nGx2MgDd2;8K;lL=8;NI{Tx-*merljc;R1T=qS zT?`W9frlI7ew)1AjC_9^AsGdCB;({7{LRC>==J`)J73wBY_cT4lr?aoS%qO zMGzR>wvT?}=>FJakDRj~p(29KZH}gK8Z~gdBC3EyJe|8ira%TzdPrN#p;ph}U5vNKbFal@d{-d z`6KW%(*4B|5c8F0e6NYvuMyZ2q5~#y^hgqW2!Wll3hm(NQIPG~jU0;m`{qv-mgyi> z8d)+0D}5VY=R0r$8UV`-Lvn}UaDUp&4NJ#2LW8#;bv?{$kWp^*3DzhI)<_7J0P8=F z9*eJ1!CN@jSp1OW{W#S~LO_(<4VE$X6u0K0!kBG5{z!1*%aCDxZh*M<|814EPBS%javpMG^LW5{?J(zGlSu&d_iTQRH zM;G|Bqy8dt{|mt#o9cmkp`VCT6_d_>!Y%<2w-z zFlaYS5YE})Y89l6TnrIPl1un6@fYDbV99l?O{7Py2#IyQxy^=+uBMJ zIeNZ7JE~a}shJR|f5StK9Bl?7uPfzLvk44($Q>}W5(49(h;fj>P_lhHIC=r*LpNl@ z;tI7-IMGX;BCHIPW;BN(=j>Qc|0H&Z9rAIaLuN9gp^hzhEOlxuH{XIk^jC?Q5K0NB z;yAjT5b8ZqsP_n=`m`rPD^jdsFs=laWBKk1`J!L$Gx?brQfm1Cd zB#gYSf;wI;GUpuCL@Q-w?VHTe^<+saQBuy%0E1nNlPJ88%Uz2v`lL81N^z2q;@ci! zqOqRDT1j9%#WVoc^Zx9pk3@`*2#k7z8Zb8ai8xg~fe}3Dm&+Wz37?=|ZsM+O!o$?7 znvfc2!?9nJc5;ibhWEIoaAh=1iKZ^mEy zYU-?rc$Pq9TbE>V^j1>KO$5|cB?TRIn?F11oQQFbz<4-xJYa0cSrOl!M{4ciD2NJm zGnfrJiT-{4JZIgG6b{dXwltDy31u6JR+?FQ%knRFF&?<=cg(4-qsi5FrwkIJSkll5O zWCOT1AR8i(Nj828Y+SHt49%^bjF9k*P4j&Bl8~HgFQE&6Y`4^(ng|9nsbPG1)&$%@% zc&8*n)K?<*R|IxDI5m!L#p!rAH?I{xfm65-TJdASS+GB^N0<%t6oyp*r)nbPPe%G| zjy{Z+M*gGcw+_7Rmkwh_A0$lVUVVEgr8f~ zcVhYPi1HUv&Lts zpw=^oVMcZqpTMtj-=D=3B&wuqBH}dyv0ndaun{RtMy(Me-6?H2mh+!;!_VPVe280k z4wnrW1+T}*;H=1ILtySksx6;JayWyC;JXB{8L?b_Qg|-nemjRf2Xi^+NupxpCiM}H zJ`an<>sPo@=kYh{H9w(VCz&MKqS{5-+6mbXnYOfW^k@Dm;Z$b`HP5vhVUc-h=?}`M0m*`+WiYm<1O68FYvoVP!2?q>*0N7NIf7L(4xm-cKx4U zkU9bKzK1P@Es$~`Nx+=y93e&A7-6Mg^9vbuOXPct;LCJu2YbGVr{Y@f*^Bs~0L3{! zC2A^`Qi6N`ih#K-!rUfc?pP2^*1o}oVK0GfDv(i-D=&vz`wetM-!SzBAs$Me1)cR0 zK8JU39hdMUk`hsOMEE-d{1`a)$I;*6l$b$3BelRns1hYqO)MlqQ9Oey{|>iGJ&#je zBv{2;6|msGN~my8tZ^&KILn0?Ei9R(U880dZ`Fyye0%F(y|M4ajxfzj=0**pI1C|<|!ENW?j>6HWSP_a11iA90>c#w+Yx)sHxFz!~>V*h#B85{lpuA*yNe%}Wr%dQB|E!+n`;$mMz{VFp3m0((&B@E*~L+nC`#(KQxZ9;G~;H_eg<_W=n z7cqV(Fse=t1HpeKG47EV{3bg`|Bkozxz$6L!K)lLtjoy=;J@ci|BfG0zV7)E+XDCo z?*8w1xKG+YL{5JYoaSkF!XW<#F2L)#C4b;jtmnS{15cC61N4pD7y6hUhj8Q2L1f*7kfodds!pW+TW@Us#zr}~vp>ClFGpm8_u zkALPSbmO+rBTm0&QjysX5#K@J2k`H}F@<(Z=^Dct_zn_qTjnV#+%0lqTG(f;IwC`- zEGp!$sci&$0RJ*q?85z&1-^n)xHT?3Svki^8ImkZsss20?n@WWk>uc1e_*9SS}*)& zc3N^WQj5ow(Uv8}@W}*_hqkPMQop|TD5X>Obq07*uD(`E%?!Tope@yqd+@c>)I13? zzFSnSn^290rPNd1>XTnbaETOkBVx3pV$~?icdaOyhP~#B>P#lNS}4ysyNEX0W4X5$ zLZOrv|A!kbqjb2PnMHyw1JW-TOWauIo!nexI5Fn*Cs}^=4Ln(a5M{5b- zALdRfs3#;rIhBiOwkE662!T_|7rKo?uuz4rEF`Id`kEB`AaF`0Bt8wBedl3+aOGM= zx5M=UxUn+u=z((B`cl9PMr#ng5OL)pRI8VtCQ`)11YRKP?t~aC!ITn-D1wNEvu6-# z6^S^fobpFWUu@T`g7_-6Z`j+wUy!3Wf7mAl`H&o=EwdmZr9hM%Ttv%$lpA5)$cFyZYbQcWNY1a^a3%5qR6p?9POSx z5hHbpvKl#uk@6m&fIXr(kvNVZZptcv8B_*Q3GpIPJV8|2KMtH`mY;}IjU_7biskQS zi2F*}aetx!T!O4At{6w|zGCyl7oe14&|`B%;vm zlF||g|5As;7Xsv>L0Ekml6){$HxA-%&!v2)KBD1gVKf^=6n=X&qSp-M^hK2KMJ@;t z6BX$G#qEX=v847)N$q3;#BK|)LWEe29wxA4(RvtXECf-CNR&blh4!BS^;}M! zm%;dsxa>+QjyqdPsbwF-4uZ(MSmSkc!-;a7y_`zo@+&DBmjL8kmhfk!@Ml3KW#+!B zq&%-ra?VmJUM)=;DxWQ0uy8Rw3}VUDea=)xsU-C@!fAYfPbFDQucBhPB~{cxZr5Te zO;S}0CpZPtkp$_ioUBRHxJ8SpNbcRml!E(du@G!tN*(aw!%0Y?&?7`4?!r>45CY47 zDo#~N`HydK7nTY6R!YYmu~L1wA}fgVt(D5*=vqq4(W|JRG{X5PfP9pMO{=9A1kaq2 zF*JMHj6%e%SxrTAt81x#+$XivoZ!-DtDjjqZa}4HmdB=G8Q1+R73X^oo*S}~`khNz zOa;ob%9fP+X4V=wHY9KwO>!Etn)*HT8T#QTmk+Ccazr}qn+`yDnp9*+Jz%!fQcC|4 zPXots1iUf5@YVv|(PdPqui79mCQyy-MYSHd4j=Z&FnAvjRh3CH)@Z!0VjMv%7}b*H zWlKxp*b1|-gdU#CjenlH5o%3IfvGz}rO!UIRA45&?c{$;iW{;4SkMa=E-NctNLM}k zY^6^i*ai{=nn3X2hHL`rXBRJBA|OtBruu0gH4F&?wXqlVOVmq=cLE`#8-~=IgOGZq z5~+u%VYG&HLW9&JBa!-fNK7Pm<0WdmI;>A0wYqQL@NkVLBBEcvNFO@9VI-hWB+*k| zq5jh+NDu^}$cS)tR6k8$sQ{;1Pqs?RW{OwayByB$9+w*j$OD7J)ZrrSa~f~OXA;;E zk=nTa0DI{#t=_Bf z+n=S~5By#y5eXTyjv_S$*Z+s9UoU1CK>7p_!dE-O79rG3Hc>kQ&Ht@{Pagk2!-y0J zEg+C^m4v(Scdm68HNXE=uuDSk8sJrF8|G+)={cgBdg?Lox+S0F1)F6k@fQHcH zsq08x1xdIsfNMIWGjLx8X#u1Y5Y*cXX)^>BZQko9xGwYFm%w$H_rCB4*w%+M1d>26 zq%iMqo9nzkNEzhy9smgOQ6cIkMBsz~pAd)?I`8|i=-o!7AdJ<8kj_G~LmCO|(+?s2 z04uMduxiSICCGEZSUnxmYcOCQ(O`8=1e}Gu3lIAtb?0DpA2+zc_OqUWm2P;IK0{cw1vDe3X7KcXKb5EboRuw3d5$FXcboo+o1E^}>1^982tr4U_9(^zruAadM7@FwxsRHtl0I$P>mL|y7E#Hl?V;;V-$@Wnz9?LN zuW|>dCK-H<+s$1&KxL={{(*IPAL9Es>-8H$C4ud?q@DR>=h^iTuwv)sma zsE6@m+_85kOP|50ZAJ&u-zbb5)2>Cl)Hs~#?Ow{ZQ2$ZE=^2>b)3@Nv_ZX2K90}FT z5ZTS>#ST7%)n`0PxlM!l>`8H_+$bFHK?Vn{DHID7_9}1~mX%{+JLWK@SKDC?hEU&p z^$~aHUEfD+_V+T>_o?*|`9JbLWlFi}B{7I(J~_o{c9|DPXWpQ)3qcH>$T8VcQ6>< z3%v&4TDDLFUpEHyL-K>3l5FLE&7*Rd9U zp6__B713yDm<_%G#t(GhIDt6X@dA8C0rMZhce@Jz&QmR1UyuJ?78bCFpQjOH+k zOgti=QEbQjHSVA1shR4lsqa}0*)f(+11MuiCcIA|Y5#<%{S&>k|BM>{&@Ou}yfHcv zK6!%qQSgdM3hL4dA1YTIR1C-bPm@-0H zx!f0@QKN=Tw~s;TAX7er`1@`Zd@*QxmInx6H1@leVAK0lv~hT5ct?;gNNPHHVeOb@)mx5KArSRq8A1UgZ29 z^V5S6f)5)mfKt1c-du|5%l>i;#c~UKmHP(dQx@|b!tqDp1#;nocM>N~b)lComnfe5 z@e<{YeSO}mPQHV@yzi(GMU{J`;YN`Jp|OZeExnjtg%LpTp$~PJTa#<9>n^tXe4(aH zEKt^~z%`K4^7N$Ph`;1WLdRO&oyH!C1*iI|mz3>-MmCfPuYsDD!ej7#u)rxw*$O>FTA_pB(~v%Q47M;*@luMG}}9Hz3@Gx&sgGWuv^92_7ap8LV^ zX!2PO2T#f8C13cTC2n<9BDX4nn}Gd8m!DR69uCn*66=Qzz4QMY(>wp}1G0YF*_-~d z7q3oI#zY7wFuV={RFdK72b4Ruqc>pZ1LY??@Vw;#0r6iv<@@<+^J6#-DlwF5XV4_y3Dyex~MAt6t^)`ZHCc*fkE$#*gE|exdqvc{~N*^@4X-A?m_*!yHC+ ztCuP8U^YCMn~>n3kSB@e^+PZ7`c(3NCN0##Jdm;ZHSZD|y diff --git a/web/share/js/kvm/switch.js b/web/share/js/kvm/switch.js index e54307f2..a33e2fd0 100644 --- a/web/share/js/kvm/switch.js +++ b/web/share/js/kvm/switch.js @@ -408,7 +408,8 @@ export function Switch() { $("switch-chain").innerHTML = content; 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) {